0

Please, I try to add item to arrayList like example below:

ArrayList<Integer> list = new ArrayList<>();

list.add(2);
list.add(5);
list.add(7);

for(int i : list ){
    if((i%2) == 0){
         list.add(i*i);
    }
}

but it throws an exception

java.util.ConcurrentModificationException

Could you please advice how can I add item like this or what kind of list (container) is to be used correctly?

Martin Plávek
  • 335
  • 1
  • 3
  • 17
  • Once you fix that error, you'll get `OutOfMemoryError` from adding powers of two infinitely. – August Dec 15 '14 at 21:41

3 Answers3

5

Use a regular for loop. Enhanced for loops do not allow you to modify the list (add/remove) while iterating over it:

for(int i = 0; i < list.size(); i++){
    int currentNumber = list.get(i);

    if((currentNumber % 2) == 0){
        list.add(currentNumber * currentNumber);
    }
}

As @MartinWoolstenhulme mentioned, this loop will not end. We iterate based on the size of the array, but since we add to the list while looping through it, it'll continue to grow in size and never end.

To avoid this, use another list. With this tactic, you no longer add to the list you are looping through. Since you are no longer modifying it (adding to it), you can use an enhanced for loop:

List<Integer> firstList = new ArrayList<>();
//add numbers to firstList

List<Integer> secondList = new ArrayList<>();

for(Integer i : firstList) {
    if((i % 2) == 0) {
        secondList.add(i * i);
     }
}

The reason I use Integer instead of int for the loop is to avoid auto-boxing and unboxing between object and primitive.

Vince
  • 14,470
  • 7
  • 39
  • 84
  • It means to create my own iterator? – Martin Plávek Dec 15 '14 at 21:27
  • 1
    good one! You do not need to create your own iterator, just use a regular for loop for (int i = 0; i < ...; i++) – Marcelo Tataje Dec 15 '14 at 21:28
  • you can create a new ArrayList, and add those new elements in that list – aurelius Dec 15 '14 at 21:32
  • 1
    Will this loop ever terminate? You add an element every time you get a number divisible by two. Since the original data contains a 2 then you get powers of 2 infinitely added to the list because the list length changes as a result of the loop. – Martin Woolstenhulme Dec 15 '14 at 21:36
  • @VinceEmigh I can't yet, but I will for sure! – Martin Plávek Dec 15 '14 at 21:38
  • @MartinWoolstenhulme It is just example what I need to do. – Martin Plávek Dec 15 '14 at 21:40
  • @MartinPlávek Yes, but in this answer as opposed to the other two answers that use a second list your loop won't terminate. In that sense this answer will cause the stack to overflow (excuse the pun and more precisely the heap is overflowing). – Martin Woolstenhulme Dec 15 '14 at 21:46
  • @MartinWoolstenhulme The question was about why he's getting a ConcurrentModificationException, not why his loop will not end. As he mentioned, it's only an example of what he actually wants. Although, for future reference, I included usage of a second list. Thanks for bringing it to my attention – Vince Dec 15 '14 at 21:57
  • @VinceEmigh However, it highlights why the ConcurrentModificationException exists, which is to prevent unexpected behavior. Granted the original intent was to prevent unexpected behavior in a multi-threaded environment, but in this case it also prevents an infinite loop. – Martin Woolstenhulme Dec 15 '14 at 23:46
0

You cannot modify the list while iterating through a for..each loop. You can rewrite your code by using a second list.

ArrayList<Integer> list = new ArrayList<>();

list.add(2);
list.add(5);
list.add(7);

ArrayList<Integer> squareList = new ArrayList<>();

squareList.addAll(list)

for (int i : list){
    if((i%2) == 0){
        squareList.add(i*i);
    }
}
Martin Woolstenhulme
  • 3,968
  • 4
  • 24
  • 25
0

You're modifying the same list you are looping through. You should be creating a new list to hold the result of your operation.

List<Integer> list = new ArrayList<>();
List<Integer> squares = new ArrayList<>();

list.add(2);
list.add(5);
list.add(7);

for (int i : list) {
    if ((i % 2) == 0) {
        squares.add(i * i);
    }
}

System.out.println(squares);

Also in Java 8

List<Integer> squares = Stream.of(2, 5, 7)
            .filter(i -> i % 2 == 0)
            .map(i -> i * i)
            .collect(Collectors.toList());
yate
  • 794
  • 4
  • 7