Home > Enterprise >  When iterating a list of lists, why does calling List.clear on the iterator remove the list from the
When iterating a list of lists, why does calling List.clear on the iterator remove the list from the

Time:11-05

Why does calling clear on the iterator here shorten the size of the batches array?

ArrayList<String> numbers = new ArrayList<>(Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10"));
    List<List<String>> numberBatches = ListUtils.partition(numbers, 2);
    for(List<String> numberBatch : numberBatches) {
        for(String number : numberBatch) {
            System.out.println(number);
        }
        numberBatch.clear();
    }

Output

1
2
5
6
9
10

CodePudding user response:

Per ListUtils documentation:

The outer list is unmodifiable, but reflects the latest state of the source list. The inner lists are sublist views of the original list, produced on demand using List.subList(int, int), and are subject to all the usual caveats about modification as explained in that API.

In essence, the inner list objects keep a reference to the index of the items in the original list. When you call List#clear, you are really removing the items from the original numbers list. However, without the other sublists updating their indices, you end up "skipping over" the remaining items:

Output    Index     numbers List
1         0         [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2         1         [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
5         2         [3, 4, 5, 6, 7, 8, 9, 10]
6         3         [3, 4, 5, 6, 7, 8, 9, 10]
9         4         [3, 4, 7, 8, 9, 10]
10        5         [3, 4, 7, 8, 9, 10]

This should probably be a candidate for throwing a ConcurrentModificationException, though the documentation does essentially warn against modifying the sublists while iterating.

CodePudding user response:

ListUtils.partition(numbers, 2) gives you view of the original list. The List<List<T>> is constructed using the method List#subList(fromIndex, toIndex). This method returns a view of the original list.

Calling clear on a subList will remove the items from the original, underlying list.

So when the loop starts the next iteration, it will continue at the index where it left off. But the values at this index have shifted already. That's why you see missing numbers in your sequence.

It is generally discouraged to modify the collection which you are iterating.

  • Related