2

I Have a scenario such like this

List<String> xxx = new ArrayList
for(String yyy : xxx){
   for(String zzz:xyxy){
     if(!zzz.equals(yyy)){
       xxx.add(zzz);
     }
   }
}

But i get java.util.ConcurrentModificationException: null exception.Can anyone help me solve this issue.? Can anyone give me alternate method to perform this ?

Sully
  • 14,672
  • 5
  • 54
  • 79

5 Answers5

10

Looking at the ArrayList API:

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.

So you're going to need to explicitly get a ListIterator and use that to properly alter your ArrayList. Also, I don't believe you can use a for-each loop because the iterators in those are separate from your explicitly retrieved iterator. I think you'll have to use a while loop:

List<String> xxx = new ArrayList<>();
ListIterator<String> iterator = xxx.listIterator();
while (iterator.hasNext()) {
    String s = iterator.next();
    for (String zzz : xyxy) {
        if (!zzz.equals(s)) {
            iterator.add(zzz); //<-- Adding is done through the iterator
        }
    }
}
awksp
  • 11,764
  • 4
  • 37
  • 44
1

Add them in another list and then add that list to xxx;

List<String> xxx = new ArrayList<>();
List<String> additional = new ArrayList<>();
for (String yyy : xxx) {
    for (String zzz : xyxy) {
        if (!zzz.equals(yyy)) {
            additional.add(zzz);
        }
    }
}
xxx.addAll(additional);
Dmitry Ginzburg
  • 7,391
  • 2
  • 37
  • 48
1

To modify a list while iterating you can declare the arraylist as "java.util.concurrent.CopyOnWriteArrayList"

public static void main(String[] args) {
    List<String> xxx = new CopyOnWriteArrayList();
    xxx.add("3");
    xxx.add("4");

    List<String> xyxy = new ArrayList();
    xyxy.add("1");
    xyxy.add("2");
    xyxy.add("3");

    for (String yyy : xxx) {
        for (String zzz : xyxy) {
            if (!zzz.equals(yyy)) {
                xxx.add(zzz);
            }
        }
    }

    System.out.println(xxx);
}
  • However, according to the online API, "The iterator will not reflect additions, removals, or changes to the list since the iterator was created". This could be problematic, depending on what OP wants. Also, `CopyOnWriteArrayList`s are horrible for performance if you don't have a ton more reads than writes – awksp May 15 '14 at 10:00
  • Agreed. CopyOnWriteArrayList will be effective when number of modifications are minimal compared to number of traversal operations. – user3636135 May 15 '14 at 10:14
  • Which doesn't seem to be the case here... – awksp May 15 '14 at 10:16
0

Don't use a foreach loop, but use a normal loop like:

int originalSize=xxx.size();
for (int i=0;i<originalSize;i++) {
    xxx.add("New string appended at the end");
}

This allows you to iterate only on the items present in the list before you start to iterate, and it works if your only operation on the list is to add some new item at the end of it.

WoDoSc
  • 2,598
  • 1
  • 13
  • 26
  • 1
    Don't do this! `xxx.size()` is chaging while `originalSize` stays the same. – Dmitry Ginzburg May 15 '14 at 09:49
  • @ginz this is done on purpose! To iterate only on the items that are originally contained in the list (and not in the new items added during the loop) – WoDoSc May 15 '14 at 09:51
  • 1
    It's not the same behavior as in author's code. – Dmitry Ginzburg May 15 '14 at 09:51
  • The intent of the OP is not really specified. But if you set the condition for ending the loop by checking xxx.size() you have the risk to have an infinite loop (if you continue to add new item). – WoDoSc May 15 '14 at 09:54
0

It means you cannot access and modify your collection (List) at the same time. To do so you must use an iterator. I dont understand what xyxy is in your code. but a possible iteration and adittion of element might look like this.

        List<String> xxx = new ArrayList<String>();

        xxx.add("hello");
        xxx.add("hi");
        xxx.add("hh");

        ListIterator<String> it = xxx.listIterator();
        while (it.hasNext()) {

            if (!it.next().equals("hi")) {
                it.remove();
                it.add("hi");

            }
        }

        System.out.println(xxx);
          }
      }
Mustafa sabir
  • 4,130
  • 1
  • 19
  • 28
  • I believe this would still throw a `ConcurrentModificationException` because you're still modifying the `ArrayList` in a way that isn't through the iterator itself – awksp May 15 '14 at 09:51