Why do I get a ConcurrentModificationException? - java

Why do I get a ConcurrentModificationException at the specified location in my code? I cannot figure out what I am doing wrong... The removeMin() method is being used to locate the min in the list pq, remove it, and return its value
import java.util.Iterator;
import java.util.LinkedList;
public class test1 {
static LinkedList<Integer> list = new LinkedList<Integer>();
public static void main(String[] args) {
list.add(10);
list.add(4);
list.add(12);
list.add(3);
list.add(7);
System.out.println(removeMin());
}
public static Integer removeMin() {
LinkedList<Integer> pq = new LinkedList<Integer>();
Iterator<Integer> itPQ = pq.iterator();
// Put contents of list into pq
for (int i = 0; i < list.size(); i++) {
pq.add(list.removeFirst());
}
int min = Integer.MAX_VALUE;
int pos = 0;
int remPos = 0;
while (itPQ.hasNext()) {
Integer element = itPQ.next(); // I get ConcurrentModificationException here
if (element < min) {
min = element;
remPos = pos;
}
pos++;
}
pq.remove(remPos);
return remPos;
}
}

An Iterator should not be considered usable once the Collection from which it was obtained is modified. (This restriction is relaxed for java.util.concurrent.* collection classes.)
You are first obtaining an Iterator for pq, then modifying pq. Once you modify pq, the Iterator itPQ is no longer valid, so when you try to use it, you get a ConcurrentModificationException.
One solution is to move Iterator<Integer> itPQ = pq.iterator(); to right before the while loop. A better approach is to do away with the explicit use of Iterator altogether:
for (Integer element : pq) {
Technically, the for-each loop uses an Iterator internally, so either way, this loop would only be valid as long as you don’t try to modify pq inside the loop.

I ran your code, and it turns out that the offending line is here:
Iterator<Integer> itPQ = pq.iterator();
This needs to come after your population of pq, so that the iterator does not have it's data updated asynchronously.
With this modification the code runs.
Now, it does not run correctly. The reason is as #Ishnark pointed out in his answer, that every time you are removing from the list, it gets smaller, and so not all of the list is being added to pq.

You face an issue because you added items to pq, using the normal .add() method after you had already created an Iterator for pq. The Iterator doesn't complain when you do the hasNext() because it sees the change in pq.
while (itPQ.hasNext()) {
...
Integer element = itPQ.next(); --> you get exception here
...
}
However, it throws an exception when you attempt to iterate through pq. According to this post, "If the iterator detects that some modifications were made without using its method (or using another iterator on the same collection), it cannot guarantee anymore that it will not pass twice on the same element or skip one, so it throws this exception."

Related

Not getting Concurrent modification exception [duplicate]

Note: I am aware of the Iterator#remove() method.
In the following code sample, I don't understand why the List.remove in main method throws ConcurrentModificationException, but not in the remove method.
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer toRemove) {
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer toRemove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
}
Here's why:
As it is says in the Javadoc:
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.
This check is done in the next() method of the iterator (as you can see by the stacktrace). But we will reach the next() method only if hasNext() delivered true, which is what is called by the for each to check if the boundary is met. In your remove method, when hasNext() checks if it needs to return another element, it will see that it returned two elements, and now after one element was removed the list only contains two elements. So all is peachy and we are done with iterating. The check for concurrent modifications does not occur, as this is done in the next() method which is never called.
Next we get to the second loop. After we remove the second number the hasNext method will check again if can return more values. It has returned two values already, but the list now only contains one. But the code here is:
public boolean hasNext() {
return cursor != size();
}
1 != 2, so we continue to the next() method, which now realizes that someone has been messing with the list and fires the exception.
Hope that clears your question up.
Summary
List.remove() will not throw ConcurrentModificationException when it removes the second last element from the list.
One way to handle it it to remove something from a copy of a Collection (not Collection itself), if applicable. Clone the original collection it to make a copy via a Constructor.
This exception may be thrown by methods that have detected concurrent
modification of an object when such modification is not permissible.
For your specific case, first off, i don't think final is a way to go considering you intend to modify the list past declaration
private static final List<Integer> integerList;
Also consider modifying a copy instead of the original list.
List<Integer> copy = new ArrayList<Integer>(integerList);
for(Integer integer : integerList) {
if(integer.equals(remove)) {
copy.remove(integer);
}
}
The forward/iterator method does not work when removing items. You can remove the element without error, but you will get a runtime error when you try to access removed items. You can't use the iterator because as pushy shows it will cause a ConcurrentModificationException, so use a regular for loop instead, but step backwards through it.
List<Integer> integerList;
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
int size= integerList.size();
//Item to remove
Integer remove = Integer.valueOf(3);
A solution:
Traverse the array in reverse order if you are going to remove a list element. Simply by going backwards through the list you avoid visiting an item that has been removed, which removes the exception.
//To remove items from the list, start from the end and go backwards through the arrayList
//This way if we remove one from the beginning as we go through, then we will avoid getting a runtime error
//for java.lang.IndexOutOfBoundsException or java.util.ConcurrentModificationException as when we used the iterator
for (int i=size-1; i> -1; i--) {
if (integerList.get(i).equals(remove) ) {
integerList.remove(i);
}
}
This snippet will always throw a ConcurrentModificationException.
The rule is "You may not modify (add or remove elements from the list) while iterating over it using an Iterator (which happens when you use a for-each loop)".
JavaDocs:
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.
Hence if you want to modify the list (or any collection in general), use iterator, because then it is aware of the modifications and hence those will be handled properly.
Hope this helps.
I had that same problem but in case that I was adding en element into iterated list.
I made it this way
public static void remove(Integer remove) {
for(int i=0; i<integerList.size(); i++) {
//here is maybe fine to deal with integerList.get(i)==null
if(integerList.get(i).equals(remove)) {
integerList.remove(i);
}
}
}
Now everything goes fine because you don't create any iterator over your list, you iterate over it "manually". And condition i < integerList.size() will never fool you because when you remove/add something into List size of the List decrement/increment..
Hope it helps, for me that was solution.
If you use copy-on-write collections it will work; however when you use list.iterator(), the returned Iterator will always reference the collection of elements as it was when ( as below )
list.iterator() was called, even if another thread modifies the collection. Any
mutating methods called on a copy-on-write–based Iterator or ListIterator
(such as add, set, or remove) will throw an UnsupportedOperationException.
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new CopyOnWriteArrayList<>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer remove) {
for(Integer integer : integerList) {
if(integer.equals(remove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer remove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(remove)) {
integerList.remove(integer);
}
}
}
}
This runs fine on Java 1.6
~ % javac RemoveListElementDemo.java
~ % java RemoveListElementDemo
~ % cat RemoveListElementDemo.java
import java.util.*;
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer remove) {
for(Integer integer : integerList) {
if(integer.equals(remove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer remove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(remove)) {
integerList.remove(integer);
}
}
}
}
~ %
In my case I did it like this:
int cursor = 0;
do {
if (integer.equals(remove))
integerList.remove(cursor);
else cursor++;
} while (cursor != integerList.size());
Change Iterator for each into for loop to solve.
And the Reason is:
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.
--Referred Java Docs.
Check your code man....
In the main method you are trying to remove the 4th element which is not there and hence the error.
In the remove() method you are trying to remove the 3rd element which is there and hence no error.

change a list while iterating or using a for each loop

I am trying to iterate (or use a for each loop) on a Linked list class and be able to change the item (when found) to a passed in parameter.
for(Item n : items)
{
if (n.getKey().equals(key))
{
n = new Item(key, value);
}
}
Does this change of data work or is it temporary (only to be lost when the activation record is deleted)?
You can't iterate over a collection and modify it. You will always get a java.util.ConcurrentModificationException. First off all you need to use an iterator, to remove the item. Then you can use a second list to store the data you want to add.
Here you are an example:
LinkedList<String> linkedList = new LinkedList<String>();
linkedList.add("This");
linkedList.add("is");
linkedList.add("an");
linkedList.add("test");
LinkedList<String> temp = new LinkedList<String>();
for (Iterator<String> iterator = linkedList.iterator(); iterator.hasNext();) {
String string = (String) iterator.next();
if(string.equals("an")) {
iterator.remove();
temp.add("a");
}
}
linkedList.addAll(temp);
You can call iterator.remove() to savely remove the current item from list.
You are using fast enumeration, which protects the list that you are iterating through. If you would like to change the data in the list, you would need to use a traditional for loop.
Basically how fast enumeration works is it makes the array read-only in the block of code because you have no access to what integer the iteration is.
You could do this:
for(int i = 0; i < items.length; i++)
{
if (n.getKey().equals(key))
{
items[i] = new Item(key, value);
}
}

java- reset list iterator to first element of the list

I need to know how to "reset" LinkedList iterator to its first element.
For example:
LinkedList<String> list;
Iterator iter=list.listIterator;
iter.next();
iter.next();
Over and over again and after many moves of the iterator, I need to "reset" the position of the iterator.
I want to ask how I can "reset" my iterator to the first element.
I know that I can get list iterator of the first element in this way:
iter= list.listIterator(1);
Is this the best solution? Or maybe I missed something in Oracle docs?
You can call listIterator method again to get an instance of iterator pointing at beginning of list:
iter = list.listIterator();
Best would be not using LinkedList at all, usually it is slower in all disciplines, and less handy. (When mainly inserting/deleting to the front, especially for big arrays LinkedList is faster)
Use ArrayList, and iterate with
int len = list.size();
for (int i = 0; i < len; i++) {
Element ele = list.get(i);
}
Reset is trivial, just loop again.
If you insist on using an iterator, then you have to use a new iterator:
iter = list.listIterator();
(I saw only once in my life an advantage of LinkedList: i could loop through whith a while loop and remove the first element)
This is an alternative solution, but one could argue it doesn't add enough value to make it worth it:
import com.google.common.collect.Iterables;
...
Iterator<String> iter = Iterables.cycle(list).iterator();
if(iter.hasNext()) {
str = iter.next();
}
Calling hasNext() will reset the iterator cursor to the beginning if it's a the end.
What you may actually want to use is an Iterable that can return a fresh Iterator multiple times by calling iterator().
//A function that needs to iterate multiple times can be given one Iterable:
public void func(Iterable<Type> ible) {
Iterator<Type> it = ible.iterator(); //Gets an iterator
while (it.hasNext()) {
it.next();
}
it = ible.iterator(); //Gets a NEW iterator, also from the beginning
while (it.hasNext()) {
it.next();
}
}
You must define what the iterator() method does just once beforehand:
void main() {
LinkedList<String> list; //This could be any type of object that has an iterator
//Define an Iterable that knows how to retrieve a fresh iterator
Iterable<Type> ible = new Iterable<Type>() {
#Override
public Iterator<Type> iterator() {
return list.listIterator(); //Define how to get a fresh iterator from any object
}
};
//Now with a single instance of an Iterable,
func(ible); //you can iterate through it multiple times.
}
If the order doesn't matter, we can re-iterate backward with the same iterator using the hasPrevious() and previous() methods:
ListIterator<T> lit = myList.listIterator(); // create just one iterator
Initially the iterator sits at the beginning, we do forward iteration:
while (lit.hasNext()) process(lit.next()); // begin -> end
Then the iterator sits at the end, we can do backward iteration:
while (lit.hasPrevious()) process2(lit.previous()); // end -> begin
Calling iterator() on a Collection impl, probably would get a new Iterator on each call.
Thus, you can simply call iterator() again to get a new one.
Code
IteratorLearn.java
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
/**
* Iterator learn.
*
* #author eric
* #date 12/30/18 4:03 PM
*/
public class IteratorLearn {
#Test
public void test() {
Collection<Integer> c = new HashSet<>();
for (int i = 0; i < 10; i++) {
c.add(i);
}
Iterator it;
// iterate,
it = c.iterator();
System.out.println("\niterate:");
while (it.hasNext()) {
System.out.printf("\t%d\n", it.next());
}
Assert.assertFalse(it.hasNext());
// consume,
it = c.iterator();
System.out.println("\nconsume elements:");
it.forEachRemaining(ele -> System.out.printf("\t%d\n", ele));
Assert.assertFalse(it.hasNext());
}
}
Output:
iterate:
0
1
2
3
4
5
6
7
8
9
consume elements:
0
1
2
3
4
5
6
7
8
9
What you can do is, set the iterator to the first position mannualy with a while loop.
while(iter.hasPrevious())
{
iter.previous();
}
when you get out of the loop you will have your iterator at the position 0
sorry any grammar mistakes
Well some of the version of java does not have a reset method for the iterator, so we are required to use the multiple iterator for number of use cases, which ultimately increases the memory consumption.
so it's simple way to use the same iterator again if needed by declaring a global function and pass the collection as argument.
for eg.
enter image description here
for eg (Written program)
package com.javalearn;
import java.util.ArrayList;
import java.util.Iterator;
public class Java_Learn {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("It's");
list.add("me.");
iter(list);
System.out.println(list.size());
System.out.println(list.indexOf("me."));
System.out.println(list.remove(3));
iter(list);
}
static void iter(ArrayList<String> arr){
Iterator itr = arr.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}

What is the best way to get the count/length/size of an iterator?

Is there a "computationally" quick way to get the count of an iterator?
int i = 0;
for ( ; some_iterator.hasNext() ; ++i ) some_iterator.next();
... seems like a waste of CPU cycles.
Using Guava library:
int size = Iterators.size(iterator);
Internally it just iterates over all elements so its just for convenience.
If you've just got the iterator then that's what you'll have to do - it doesn't know how many items it's got left to iterate over, so you can't query it for that result. There are utility methods that will seem to do this efficiently (such as Iterators.size() in Guava), but underneath they're just consuming the iterator and counting as they go, the same as in your example.
However, many iterators come from collections, which you can often query for their size. And if it's a user made class you're getting the iterator for, you could look to provide a size() method on that class.
In short, in the situation where you only have the iterator then there's no better way, but much more often than not you have access to the underlying collection or object from which you may be able to get the size directly.
Your code will give you an exception when you reach the end of the iterator. You could do:
int i = 0;
while(iterator.hasNext()) {
i++;
iterator.next();
}
If you had access to the underlying collection, you would be able to call coll.size()...
EDIT
OK you have amended...
You will always have to iterate. Yet you can use Java 8, 9 to do the counting without looping explicitely:
Iterable<Integer> newIterable = () -> iter;
long count = StreamSupport.stream(newIterable.spliterator(), false).count();
Here is a test:
public static void main(String[] args) throws IOException {
Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4, 5).iterator();
Iterable<Integer> newIterable = () -> iter;
long count = StreamSupport.stream(newIterable.spliterator(), false).count();
System.out.println(count);
}
This prints:
5
Interesting enough you can parallelize the count operation here by changing the parallel flag on this call:
long count = StreamSupport.stream(newIterable.spliterator(), *true*).count();
Using Guava library, another option is to convert the Iterable to a List.
List list = Lists.newArrayList(some_iterator);
int count = list.size();
Use this if you need also to access the elements of the iterator after getting its size. By using Iterators.size() you no longer can access the iterated elements.
If all you have is the iterator, then no, there is no "better" way. If the iterator comes from a collection you could as that for size.
Keep in mind that Iterator is just an interface for traversing distinct values, you would very well have code such as this
new Iterator<Long>() {
final Random r = new Random();
#Override
public boolean hasNext() {
return true;
}
#Override
public Long next() {
return r.nextLong();
}
#Override
public void remove() {
throw new IllegalArgumentException("Not implemented");
}
};
or
new Iterator<BigInteger>() {
BigInteger next = BigInteger.ZERO;
#Override
public boolean hasNext() {
return true;
}
#Override
public BigInteger next() {
BigInteger current = next;
next = next.add(BigInteger.ONE);
return current;
}
#Override
public void remove() {
throw new IllegalArgumentException("Not implemented");
}
};
There is no more efficient way, if all you have is the iterator. And if the iterator can only be used once, then getting the count before you get the iterator's contents is ... problematic.
The solution is either to change your application so that it doesn't need the count, or to obtain the count by some other means. (For example, pass a Collection rather than Iterator ...)
for Java 8 you could use,
public static int getIteratorSize(Iterator iterator){
AtomicInteger count = new AtomicInteger(0);
iterator.forEachRemaining(element -> {
count.incrementAndGet();
});
return count.get();
}
To get the size of an Iterable
Iterable<Users> users = usersRepository.findUsersByLocation("IND");
Now assert the size of users of Type Iterable
assertEquals(2, ((Collection<Users>)users).size());
To get quickly the size :
[...iterator].length
iterator object contains the same number of elements what your collection contained.
List<E> a =...;
Iterator<E> i = a.iterator();
int size = a.size();//Because iterators size is equal to list a's size.
But instead of getting the size of iterator and iterating through index 0 to that size, it is better to iterate through the method next() of the iterator.

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

Categories