ArrayList.subList().spliterator() is not late-binding

Tagir F. Valeev amaembo at gmail.com
Fri Jan 29 04:32:24 UTC 2016


Hello!

When reviewing 8079136 I noticed that
ArrayList.subList().spliterator() is not late-binding:

List<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4)).subList(0, 3);
Stream<Integer> s = list.stream();
list.add(5);
s.findFirst();
--> Exception in thread "main" java.util.ConcurrentModificationException

This works correctly for other list implementation (for example,
replacing ArrayList with LinkedList makes this code working). As
Collection.spliterator() spec says:

> In order to preserve expected laziness behavior for the stream() and
> parallelStream() methods, spliterators should either have the
> characteristic of IMMUTABLE or CONCURRENT, or be late-binding. If
> none of these is practical, the overriding class should describe the
> spliterator's documented policy of binding and structural
> interference, and should override the stream() and parallelStream()
> methods to create streams using a Supplier of the spliterator

None of these is true for ArrayList.subList().spliterator(): it's not
IMMUTABLE, not CONCURRENT, not late-binding, the binding policy is not
documented and stream()/parallelStream() methods are not overridden.

Is this an issue?

Actually to my opinion late-binding spliterator behavior is a mistake.
Nobody cares about it as nobody modifies the source between stream
creation and terminal operation call. On the other hand, this
requirement adds implementation complexity and I already found the
second late-binding problem in existing code (the first one was with
Pattern.splitAsStream). Also it's not documented that Stream.concat
may bind the late-binding source, but nobody cares anyways. Life would
be easier without late-binding spliterators.

With best regards,
Tagir Valeev.




More information about the core-libs-dev mailing list