Ways to iterate over a list in Java - java
Being somewhat new to the Java language I'm trying to familiarize myself with all the ways (or at least the non-pathological ones) that one might iterate through a list (or perhaps other collections) and the advantages or disadvantages of each.
Given a List<E> list object, I know of the following ways to loop through all elements:
Basic for loop (of course, there're equivalent while / do while loops as well)
// Not recommended (see below)!
for (int i = 0; i < list.size(); i++) {
E element = list.get(i);
// 1 - can call methods of element
// 2 - can use 'i' to make index-based calls to methods of list
// ...
}
Note: As #amarseillan pointed out, this form is a poor choice
for iterating over Lists, because the actual implementation of
the get method may not be as efficient as when using an Iterator.
For example, LinkedList implementations must traverse all of
the elements preceding i to get the i-th element.
In the above example there's no way for the List implementation to
"save its place" to make future iterations more efficient.
For an ArrayList it doesn't really matter, because the complexity/cost of get is constant time (O(1)) whereas for a LinkedList is it proportional to the size of the list (O(n)).
For more information about the computational complexity of the built-in Collections implementations, check out this question.
Enhanced for loop (nicely explained in this question)
for (E element : list) {
// 1 - can call methods of element
// ...
}
Iterator
for (Iterator<E> iter = list.iterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// ...
}
ListIterator
for (ListIterator<E> iter = list.listIterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// 3 - can use iter.add(...) to insert a new element into the list
// between element and iter->next()
// 4 - can use iter.set(...) to replace the current element
// ...
}
Functional Java
list.stream().map(e -> e + 1); // Can apply a transformation function for e
Iterable.forEach, Stream.forEach, ...
(A map method from Java 8's Stream API (see #i_am_zero's answer).)
In Java 8 collection classes that implement Iterable (for example, all Lists) now have a forEach method, which can be used instead of the for loop statement demonstrated above. (Here is another question that provides a good comparison.)
Arrays.asList(1,2,3,4).forEach(System.out::println);
// 1 - can call methods of an element
// 2 - would need reference to containing object to remove an item
// (TODO: someone please confirm / deny this)
// 3 - functionally separates iteration from the action
// being performed with each item.
Arrays.asList(1,2,3,4).stream().forEach(System.out::println);
// Same capabilities as above plus potentially greater
// utilization of parallelism
// (caution: consequently, order of execution is not guaranteed,
// see [Stream.forEachOrdered][stream-foreach-ordered] for more
// information about this).
What other ways are there, if any?
(BTW, my interest does not stem at all from a desire to optimize performance; I just want to know what forms are available to me as a developer.)
The three forms of looping are nearly identical. The enhanced for loop:
for (E element : list) {
. . .
}
is, according to the Java Language Specification, identical in effect to the explicit use of an iterator with a traditional for loop. In the third case, you can only modify the list contents by removing the current element and, then, only if you do it through the remove method of the iterator itself. With index-based iteration, you are free to modify the list in any way. However, adding or removing elements that come before the current index risks having your loop skipping elements or processing the same element multiple times; you need to adjust the loop index properly when you make such changes.
In all cases, element is a reference to the actual list element. None of the iteration methods makes a copy of anything in the list. Changes to the internal state of element will always be seen in the internal state of the corresponding element on the list.
Essentially, there are only two ways to iterate over a list: by using an index or by using an iterator. The enhanced for loop is just a syntactic shortcut introduced in Java 5 to avoid the tedium of explicitly defining an iterator. For both styles, you can come up with essentially trivial variations using for, while or do while blocks, but they all boil down to the same thing (or, rather, two things).
EDIT: As #iX3 points out in a comment, you can use a ListIterator to set the current element of a list as you are iterating. You would need to use List#listIterator() instead of List#iterator() to initialize the loop variable (which, obviously, would have to be declared a ListIterator rather than an Iterator).
Example of each kind listed in the question:
ListIterationExample.java
import java.util.*;
public class ListIterationExample {
public static void main(String []args){
List<Integer> numbers = new ArrayList<Integer>();
// populates list with initial values
for (Integer i : Arrays.asList(0,1,2,3,4,5,6,7))
numbers.add(i);
printList(numbers); // 0,1,2,3,4,5,6,7
// replaces each element with twice its value
for (int index=0; index < numbers.size(); index++) {
numbers.set(index, numbers.get(index)*2);
}
printList(numbers); // 0,2,4,6,8,10,12,14
// does nothing because list is not being changed
for (Integer number : numbers) {
number++; // number = new Integer(number+1);
}
printList(numbers); // 0,2,4,6,8,10,12,14
// same as above -- just different syntax
for (Iterator<Integer> iter = numbers.iterator(); iter.hasNext(); ) {
Integer number = iter.next();
number++;
}
printList(numbers); // 0,2,4,6,8,10,12,14
// ListIterator<?> provides an "add" method to insert elements
// between the current element and the cursor
for (ListIterator<Integer> iter = numbers.listIterator(); iter.hasNext(); ) {
Integer number = iter.next();
iter.add(number+1); // insert a number right before this
}
printList(numbers); // 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
// Iterator<?> provides a "remove" method to delete elements
// between the current element and the cursor
for (Iterator<Integer> iter = numbers.iterator(); iter.hasNext(); ) {
Integer number = iter.next();
if (number % 2 == 0) // if number is even
iter.remove(); // remove it from the collection
}
printList(numbers); // 1,3,5,7,9,11,13,15
// ListIterator<?> provides a "set" method to replace elements
for (ListIterator<Integer> iter = numbers.listIterator(); iter.hasNext(); ) {
Integer number = iter.next();
iter.set(number/2); // divide each element by 2
}
printList(numbers); // 0,1,2,3,4,5,6,7
}
public static void printList(List<Integer> numbers) {
StringBuilder sb = new StringBuilder();
for (Integer number : numbers) {
sb.append(number);
sb.append(",");
}
sb.deleteCharAt(sb.length()-1); // remove trailing comma
System.out.println(sb.toString());
}
}
The basic loop is not recommended as you do not know the implementation of the list.
If that was a LinkedList, each call to
list.get(i)
would be iterating over the list, resulting in N^2 time complexity.
A JDK8-style iteration:
public class IterationDemo {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3);
list.stream().forEach(elem -> System.out.println("element " + elem));
}
}
In Java 8 we have multiple ways to iterate over collection classes.
Using Iterable forEach
The collections that implement Iterable (for example all lists) now have forEach method. We can use method-reference introduced in Java 8.
Arrays.asList(1,2,3,4).forEach(System.out::println);
Using Streams forEach and forEachOrdered
We can also iterate over a list using Stream as:
Arrays.asList(1,2,3,4).stream().forEach(System.out::println);
Arrays.asList(1,2,3,4).stream().forEachOrdered(System.out::println);
We should prefer forEachOrdered over forEach because the behaviour of forEach is explicitly nondeterministic where as the forEachOrdered performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order. So forEach does not guarantee that the order would be kept.
The advantage with streams is that we can also make use of parallel streams wherever appropriate. If the objective is only to print the items irrespective of the order then we can use parallel stream as:
Arrays.asList(1,2,3,4).parallelStream().forEach(System.out::println);
I don't know what you consider pathological, but let me provide some alternatives you could have not seen before:
List<E> sl= list ;
while( ! sl.empty() ) {
E element= sl.get(0) ;
.....
sl= sl.subList(1,sl.size());
}
Or its recursive version:
void visit(List<E> list) {
if( list.isEmpty() ) return;
E element= list.get(0) ;
....
visit(list.subList(1,list.size()));
}
Also, a recursive version of the classical for(int i=0... :
void visit(List<E> list,int pos) {
if( pos >= list.size() ) return;
E element= list.get(pos) ;
....
visit(list,pos+1);
}
I mention them because you are "somewhat new to Java" and this could be interesting.
You can use forEach starting from Java 8:
List<String> nameList = new ArrayList<>(
Arrays.asList("USA", "USSR", "UK"));
nameList.forEach((v) -> System.out.println(v));
In java 8 you can use List.forEach() method with lambda expression to iterate over a list.
import java.util.ArrayList;
import java.util.List;
public class TestA {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Apple");
list.add("Orange");
list.add("Banana");
list.forEach(
(name) -> {
System.out.println(name);
}
);
}
}
In Java 8 or above, you can iterate a Hashset using forEach() method.
import java.util.HashSet;
public class HashSetTest {
public static void main(String[] args) {
HashSet<String> hSet = new HashSet<String>();
// Adding elements into your HashSet usind add()
hSet.add("test1");
hSet.add("test2");
hSet.add("test3");
// Iterating over hash set items
hSet.forEach(x -> System.out.println(x));
// Or you can write shorter:
hSet.forEach(System.out::println);
}
}
For a backward search you should use the following:
for (ListIterator<SomeClass> iterator = list.listIterator(list.size()); iterator.hasPrevious();) {
SomeClass item = iterator.previous();
...
item.remove(); // For instance.
}
If you want to know a position, use iterator.previousIndex(). It also helps to write an inner loop that compares two positions in the list (iterators are not equal).
Right, many alternatives are listed. The easiest and cleanest would be just using the enhanced for statement as below. The Expression is of some type that is iterable.
for ( FormalParameter : Expression ) Statement
For example, to iterate through, List<String> ids, we can simply so,
for (String str : ids) {
// Do something
}
Above you'll find all differents ways to iterate over a LIST.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class test1 {
public static void main(String[] args) {
//******* Exercise 1 : Write a Java program to create a new array list, add some colors (string) and print out the collection.
List<String> colors = new ArrayList<String>();
colors.add("Black");
colors.add("Red");
colors.add("Green");
colors.add("Blue");
System.out.println(colors);
//******* Exercise 2 : Write a Java program to iterate through all elements in a array list.
System.out.println("//******* Exercise 2");
List<Integer> list2 = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
// iteration type 1 : using FOR loop
System.out.println("// iteration type 1");
for(Integer nb : list2) {
System.out.print(nb + ", ");
}
System.out.println("\n");
// iteration type 2 : using FOR loop
System.out.println("// iteration type 2");
for(int i=0; i < list2.size(); i++) {
System.out.print(list2.get(i) + ", ");
}System.out.println("\n");
// iteration type 3 : using Do-While loop
System.out.println("// iteration type 3");
int index21 = 0;
do {
System.out.print(list2.get(index21) + ", ");
index21++;
}while(index21<list2.size());
System.out.println("\n");
// iteration type 4 : using While loop
System.out.println("// iteration type 4");
int index22 = 0;
while(index22<list2.size()) {
System.out.print(list2.get(index22) + ", ");
index22++;
}
System.out.println("\n");
// iteration type 5 : using Iterable forEach loop
System.out.println("// iteration type 5");
list2.forEach(elt -> {
System.out.print(elt + ", ");
});
System.out.println("\n");
// iteration type 6 : using Iterator
System.out.println("// iteration type 6");
Iterator<Integer> listIterator = list2.iterator();
while(listIterator.hasNext()) {
System.out.print( listIterator.next() + ", ");
}
System.out.println("\n");
// iteration type 7 : using Iterator (From the beginning)
System.out.println("// iteration type 7");
ListIterator<Integer> listIterator21 = list2.listIterator(list2.size());
while(listIterator21.hasPrevious()) {
System.out.print( listIterator21.previous() + ", ");
}
System.out.println("\n");
// iteration type 8 : using Iterator (From the End)
System.out.println("// iteration type 8");
ListIterator<Integer> listIterator22 = list2.listIterator();
while(listIterator22.hasNext()) {
System.out.print( listIterator22.next() + ", ");
}
System.out.println("\n");
}
}
You could always switch out the first and third examples with a while loop and a little more code. This gives you the advantage of being able to use the do-while:
int i = 0;
do{
E element = list.get(i);
i++;
}
while (i < list.size());
Of course, this kind of thing might cause a NullPointerException if the list.size() returns 0, becuase it always gets executed at least once. This can be fixed by testing if element is null before using its attributes / methods tho. Still, it's a lot simpler and easier to use the for loop
Related
ConcurrentModificationException When removing element using list iterator java
I have an issue removing the 1st and 2nd element of my list even by using the iterator. I have read the following threads but can't fix my issue (those were the most relevant but I checked other material as well): ConcurrentModificationException when trying remove element from list Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop So my code looks like this: List<List<String>> list = cnf.read(); List<List<String>> nlist = new ArrayList<>(); for (List<String> l : list) { if (l.size() <= 3) { nlist.add(l); } else { int size = l.size(); while (size > 3) { List<String> three = l.subList(0, 2); three.add("Y" + (count++)); //Iterator itr = l.iterator(); ListIterator itr = l.listIterator(); int v = 0; while (itr.hasNext()) { itr.next(); if (v == 0 || v == 1) { itr.remove(); v++; } } l.add(0, "Y" + (count++)); size--; nlist.add(three); } nlist.add(l); } } for (List<String> l : nlist) { System.out.println(l.toString()); System.out.println(l.size()); } I get a ConcurrentModificationException at the print statement here : System.out.println(l.toString()); I tried using iterators for my 2 for loops as well but It doesn't seem to make a difference! I am new to posting questions so let me know If I am doing it right! Thank you.
After A long debugging, here is the solution. The sublist function passes by reference and not by value, a sublist created by ArrayList.subList call keeps a reference to the original list and accesses its elementData array directly. For this reason, when adding an element to the "three" list, we alter the state of the original list. this happens here: three.add("Y" + (count++)); A way of fixing it for this specific case is to create and initialize the "three" list the following way: String one = l.get(0); String two = l.get(1); List<String> three = new ArrayList<>(); three.add(one); three.add(two); three.add("Y" + (count)); This allows us to manipulate our lists without getting Concurrency Exceptions (ConcurrentModificationException). However, if you are manipulating big lists, I would suggest you use another less hardcoded method for list creation. I will mark this thread as answered and hope it helps people.
Deleting specific object from ArrayList using for-loop
I am trying to delete one object from an ArrayList, but after iterating through the list with the for loop i'm stuck at what to do next. nameInput is a lowercase string from the user. If i run this it prints the object from arr list equal to the input from nameInput. But I cannot understand how to go from printing that object to deleting it? I'm sure this is a stupid question but the 50+ answers i have read and tried all seem to fail me (or more likely I fail to understand them). I have tried the list.remove and removeIf. private ArrayList<Arr> arr = new ArrayList<>(); private void removeItem() { for (Object arr : arr) { if (((Arr) arr).getName().equals(nameInput())) { System.out.println(arr); break; } else { System.out.println("Error"); } } }
Using for loop List<Arr> arr = new ArrayList<>(); for (Arr item : arr) { if (item.getName().equals(nameInput())) { arr.remove(item); break; } } If not call break after remove element, you get ConcurrentElementException Note from #Aomine: you have to implement correct Arr.equals() method. Using Iterator List<Arr> arr = new ArrayList<>(); Iterator<Arr> it = arr.iterator(); while (it.hasNext()) { Arr items = it.next(); if (item.getName().equals(nameInput())) { it.remove(); break; // you can continue iterating and remove another item } } Using Streams List<Arr> arr = new ArrayList<>(); arr.removeIf(item -> item.getName().equals(nameInput())); Remove all items that match given condition This is not good to remove element from ArrayList. In case you know that you have to remove element from the middle of the List, do use LinkedList.
You are trying to remove an item while you are traversing/iterating the list in the for loop. You cannot remove an item from the list iterating it in a for loop. Use an Iterator instead and invoke arr.remove().
If you use Java 8 you could do private void removeItem() { arr.removeIf(t -> t.getName().equals(nameInput)); } Note that this will remove all objects with name equal to nameInput Also you should change your declaration of arr to List<Arr> arr = new ArrayList<>();
A couple of things here... The loop variable receiver type should ideally be Arr instead of Object as the list contains Arr objects. This also means you no longer need the cast you're performing. You could remove the item via remove(Object o) but this requires overriding equals and hashcode based on name only. Another option is via an iterator but this would mean changing your code completely. Thus, to keep it as close to your code as possible you can use a for loop; get the index which the object is located and then remove. Thus, you can do: for(int i = 0; i < arr.size(); i++){ if (arr.get(i).getName().equals(nameInput)) { Arr obj = arr.remove(i); // remove the item by index System.out.println(obj); // print the object break; // terminate the loop iteration } }
How to obtain first 5 values from a LinkedHashSet?
I have a LinkedHashSet which contains multiple number of values. LinkedHashSet<String> lhs = new LinkedHashSet<String>(); I want to iterate through the set of values and display the first five values from the number of items stored in the set. I have used a for loop to iterate through values and display data, see below: for (String sent : lhs) { text.append(sent); } This outputs all the values stored in the LinkedHashSet. What alterations should I make to my code in order to only get the first 5 values from the set.
You can get your sets Iterator Iterator<String> it = yourSet.iterator(); and move to next() element N times (assuming that it still hasNext() element) int counter = 0; while(it.hasNext() && counter++ < N){ String element = it.next(); ... }
int i = 0; for (String sentences : lhs) { if (i > 4) break; text.append(sentences); i++; }
If you had java8, then I would suggest something like this: yourLinkedHashSet .stream() .limit(5) .forEachOrdered(text::append); Explanation: stream() will take one String after another from the collection limit(5) will stop the calculations after five elements are processed forEachOrdered(...) takes an action for each item, one after another text::append is the action to be done per item
You can use subList without counter declaration Iterator<String> iter = new ArrayList<>(lhs).subList(5, lhs.size()) .iterator(); while (iter.hasNext()) { text.append(iter.next()); }
Java - Collection.remove() behaves differently in different conditions
This is a follow up to my previous question : Collection - Iterator.remove() vs Collection.remove() The below two pieces of code , which apparently differs only by a single line , but one throws exception and other don't . Can you please explain the difference ? List<String> list = new ArrayList<String> (Arrays.asList("noob1","noob2","noob3")); System.out.println(list); for (String str : list) { if (str.equals("noob2")) { list.remove(str); } } runs fine , but if i change the condition to if (!str.equals("noob2")) the code throws exception !
What happens in this situation is you are removing the second list element. List<String> list = new ArrayList<String> (Arrays.asList("noob1", "noob2", "noob3", "noob4")); System.out.println(list); for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) { String str = iterator.next(); if (str.equals("noob3")) { System.out.println("Checking "+str); list.remove(str); } } System.out.println(list); prints [noob1, noob2, noob3, noob4] Checking noob1 Checking noob2 Checking noob3 [noob1, noob2, noob4] By removing the second last element you have reduced the size to the number of elements which you have iterated over. // from ArrayList.Itr public boolean hasNext() { return cursor != size; } This causes the loop to exit early before the concurrent modifcation check is performed in next(). If you remove any other element next() is called and you get a CME. BTW Something which also bypasses the check is for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) { String str = iterator.next(); System.out.println("Checking "+str); if (str.equals("noob2")) { list.remove("noob1"); list.remove("noob3"); } } as long as the size of the collection is the same as the index it is up to, the check is not performed.
The for loop is just a simplified syntax for an iterator scan of the list. The iterator may throw an exception if the list is modified under it, but it is not guaranteed. Because of hasNext, iterators are often working one element ahead, making the first case less likely to be affected by list modification. By the time "noob2" is removed, the iterator already knows about "noob3".
Actually you should never remove collections' elements during "casual" iterating. When you have to modify your collection in some loop you have to use iterator to make these operations. public class Test { public static void main(String... args) { List<String> list = new ArrayList<String>(Arrays.asList("noob1", "noob2", "noob3")); System.out.println(list); for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) { String str = iterator.next(); if (!str.equals("noob2")) { iterator.remove(); } } System.out.println(list); } }
I suppose the exception is thown because you are trying to change a collection you are looping on... and not because the if condition. I suggest you to create a new list only containing the items that verify the condition. Add them to the new list and avoid to change the original collection.
It's because you are trying to remove from a Collection you are currently iterating through. Making a minor alteration you can do what you want to do: String[] strValues = {"noob1","noob2","noob3"}; // <<< Array List<String> list = new ArrayList<String>(Arrays.asList(strValues)); System.out.println(list); for (String str : strValues) { // << List is duplicate of array so can iterate through array if (!str.equals("noob2")) { list.remove(str); } } That should work. Hopefully
Well, your first case doesn't throw the Exception because, the iterator returns false for Iterator.hasNext() at index 2 as you remove the element at index 1. Iterator<String> itr = list.iterator(); while(itr.hasNext()){ String s= itr.next(); if(s.equals("noob2")){ list.remove(s); // size of the list is 2 here System.out.println(itr.hasNext());// this returns false as it doesn't have anything at index 2 now.(on 2nd iteration ) } } You can test it clearly using a simple for-loop: for (int i=0; i<list.size(); i++) { if (list.get(i).equals("noob2")) { System.out.println(list.get(i)); System.out.println(list.size()); list.remove(list.get(i)); System.out.println(list.size()); } } Output: [noob1, noob2, noob3] noob2 3 2 Notice the size of the list after you remove the element, which fails after incrementing. 2<2 which is false
How to avoid java.util.ConcurrentModificationException when iterating through and removing elements from an ArrayList
I have an ArrayList that I want to iterate over. While iterating over it I have to remove elements at the same time. Obviously this throws a java.util.ConcurrentModificationException. What is the best practice to handle this problem? Should I clone the list first? I remove the elements not in the loop itself but another part of the code. My code looks like this: public class Test() { private ArrayList<A> abc = new ArrayList<A>(); public void doStuff() { for (A a : abc) a.doSomething(); } public void removeA(A a) { abc.remove(a); } } a.doSomething might call Test.removeA();
Two options: Create a list of values you wish to remove, adding to that list within the loop, then call originalList.removeAll(valuesToRemove) at the end Use the remove() method on the iterator itself. Note that this means you can't use the enhanced for loop. As an example of the second option, removing any strings with a length greater than 5 from a list: List<String> list = new ArrayList<String>(); ... for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) { String value = iterator.next(); if (value.length() > 5) { iterator.remove(); } }
From the JavaDocs of the ArrayList The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.
You are trying to remove value from list in advanced "for loop", which is not possible, even if you apply any trick (which you did in your code). Better way is to code iterator level as other advised here. I wonder how people have not suggested traditional for loop approach. for( int i = 0; i < lStringList.size(); i++ ) { String lValue = lStringList.get( i ); if(lValue.equals("_Not_Required")) { lStringList.remove(lValue); i--; } } This works as well.
In Java 8 you can use the Collection Interface and do this by calling the removeIf method: yourList.removeIf((A a) -> a.value == 2); More information can be found here
You should really just iterate back the array in the traditional way Every time you remove an element from the list, the elements after will be push forward. As long as you don't change elements other than the iterating one, the following code should work. public class Test(){ private ArrayList<A> abc = new ArrayList<A>(); public void doStuff(){ for(int i = (abc.size() - 1); i >= 0; i--) abc.get(i).doSomething(); } public void removeA(A a){ abc.remove(a); } }
While iterating the list, if you want to remove the element is possible. Let see below my examples, ArrayList<String> names = new ArrayList<String>(); names.add("abc"); names.add("def"); names.add("ghi"); names.add("xyz"); I have the above names of Array list. And i want to remove the "def" name from the above list, for(String name : names){ if(name.equals("def")){ names.remove("def"); } } The above code throws the ConcurrentModificationException exception because you are modifying the list while iterating. So, to remove the "def" name from Arraylist by doing this way, Iterator<String> itr = names.iterator(); while(itr.hasNext()){ String name = itr.next(); if(name.equals("def")){ itr.remove(); } } The above code, through iterator we can remove the "def" name from the Arraylist and try to print the array, you would be see the below output. Output : [abc, ghi, xyz]
Do the loop in the normal way, the java.util.ConcurrentModificationException is an error related to the elements that are accessed. So try: for(int i = 0; i < list.size(); i++){ lista.get(i).action(); }
Here is an example where I use a different list to add the objects for removal, then afterwards I use stream.foreach to remove elements from original list : private ObservableList<CustomerTableEntry> customersTableViewItems = FXCollections.observableArrayList(); ... private void removeOutdatedRowsElementsFromCustomerView() { ObjectProperty<TimeStamp> currentTimestamp = new SimpleObjectProperty<>(TimeStamp.getCurrentTime()); long diff; long diffSeconds; List<Object> objectsToRemove = new ArrayList<>(); for(CustomerTableEntry item: customersTableViewItems) { diff = currentTimestamp.getValue().getTime() - item.timestamp.getValue().getTime(); diffSeconds = diff / 1000 % 60; if(diffSeconds > 10) { // Element has been idle for too long, meaning no communication, hence remove it System.out.printf("- Idle element [%s] - will be removed\n", item.getUserName()); objectsToRemove.add(item); } } objectsToRemove.stream().forEach(o -> customersTableViewItems.remove(o)); }
One option is to modify the removeA method to this - public void removeA(A a,Iterator<A> iterator) { iterator.remove(a); } But this would mean your doSomething() should be able to pass the iterator to the remove method. Not a very good idea. Can you do this in two step approach : In the first loop when you iterate over the list , instead of removing the selected elements , mark them as to be deleted. For this , you may simply copy these elements ( shallow copy ) into another List. Then , once your iteration is done , simply do a removeAll from the first list all elements in the second list.
In my case, the accepted answer is not working, It stops Exception but it causes some inconsistency in my List. The following solution is perfectly working for me. List<String> list = new ArrayList<>(); List<String> itemsToRemove = new ArrayList<>(); for (String value: list) { if (value.length() > 5) { // your condition itemsToRemove.add(value); } } list.removeAll(itemsToRemove); In this code, I have added the items to remove, in another list and then used list.removeAll method to remove all required items.
Instead of using For each loop, use normal for loop. for example,the below code removes all the element in the array list without giving java.util.ConcurrentModificationException. You can modify the condition in the loop according to your use case. for(int i=0; i<abc.size(); i++) { e.remove(i); }
Sometimes old school is best. Just go for a simple for loop but make sure you start at the end of the list otherwise as you remove items you will get out of sync with your index. List<String> list = new ArrayList<>(); for (int i = list.size() - 1; i >= 0; i--) { if ("removeMe".equals(list.get(i))) { list.remove(i); } }
You can also use CopyOnWriteArrayList instead of an ArrayList. This is the latest recommended approach by from JDK 1.5 onwards.
Do somehting simple like this: for (Object object: (ArrayList<String>) list.clone()) { list.remove(object); }
An alternative Java 8 solution using stream: theList = theList.stream() .filter(element -> !shouldBeRemoved(element)) .collect(Collectors.toList()); In Java 7 you can use Guava instead: theList = FluentIterable.from(theList) .filter(new Predicate<String>() { #Override public boolean apply(String element) { return !shouldBeRemoved(element); } }) .toImmutableList(); Note, that the Guava example results in an immutable list which may or may not be what you want.
for (A a : new ArrayList<>(abc)) { a.doSomething(); abc.remove(a); }
"Should I clone the list first?" That will be the easiest solution, remove from the clone, and copy the clone back after removal. An example from my rummikub game: SuppressWarnings("unchecked") public void removeStones() { ArrayList<Stone> clone = (ArrayList<Stone>) stones.clone(); // remove the stones moved to the table for (Stone stone : stones) { if (stone.isOnTable()) { clone.remove(stone); } } stones = (ArrayList<Stone>) clone.clone(); sortStones(); }
I arrive late I know but I answer this because I think this solution is simple and elegant: List<String> listFixed = new ArrayList<String>(); List<String> dynamicList = new ArrayList<String>(); public void fillingList() { listFixed.add("Andrea"); listFixed.add("Susana"); listFixed.add("Oscar"); listFixed.add("Valeria"); listFixed.add("Kathy"); listFixed.add("Laura"); listFixed.add("Ana"); listFixed.add("Becker"); listFixed.add("Abraham"); dynamicList.addAll(listFixed); } public void updatingListFixed() { for (String newList : dynamicList) { if (!listFixed.contains(newList)) { listFixed.add(newList); } } //this is for add elements if you want eraser also String removeRegister=""; for (String fixedList : listFixed) { if (!dynamicList.contains(fixedList)) { removeResgister = fixedList; } } fixedList.remove(removeRegister); } All this is for updating from one list to other and you can make all from just one list and in method updating you check both list and can eraser or add elements betwen list. This means both list always it same size
Use Iterator instead of Array List Have a set be converted to iterator with type match And move to the next element and remove Iterator<Insured> itr = insuredSet.iterator(); while (itr.hasNext()) { itr.next(); itr.remove(); } Moving to the next is important here as it should take the index to remove element.
List<String> list1 = new ArrayList<>(); list1.addAll(OriginalList); List<String> list2 = new ArrayList<>(); list2.addAll(OriginalList); This is also an option.
If your goal is to remove all elements from the list, you can iterate over each item, and then call: list.clear()
What about of import java.util.Collections; List<A> abc = Collections.synchronizedList(new ArrayList<>());
ERROR There was a mistake when I added to the same list from where I took elements: fun <T> MutableList<T>.mathList(_fun: (T) -> T): MutableList<T> { for (i in this) { this.add(_fun(i)) <--- ERROR } return this <--- ERROR } DECISION Works great when adding to a new list: fun <T> MutableList<T>.mathList(_fun: (T) -> T): MutableList<T> { val newList = mutableListOf<T>() <--- DECISION for (i in this) { newList.add(_fun(i)) <--- DECISION } return newList <--- DECISION }
Just add a break after your ArrayList.remove(A) statement