Just iterating below list & adding into another shared mutable list via java 8 streams.
List<String> list1 = Arrays.asList("A1","A2","A3","A4","A5","A6","A7","A8","B1","B2","B3");
List<String> list2 = new ArrayList<>();
Consumer<String> c = t -> list2.add(t.startsWith("A") ? t : "EMPTY");
list1.stream().forEach(c);
list1.parallelStream().forEach(c);
list1.forEach(c);
What is the difference between above three iteration & which one we need to use. Are there any considerations?
Advertisement
Answer
Functionally speaking,for the simple cases they are almost the same, but generally speaking, there are some hidden differences:
- Lets start by quoting from Javadoc of
forEachfor iterable use-cases stating that:
performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception.
and also we can iterate over a collection and perform a given action on each element – by just passing a class that implements the Consumer interface
void forEach(Consumer<? super T> action)
- The order of
Stream.forEachis random whileIterable.forEachis always executed in the iteration order of theIterable.
- If
Iterable.forEachis iterating over a synchronized collection,Iterable.forEachtakes the collection’s lock once and holds it across all the calls to the action method. The Stream.forEach call uses the collection’s spliterator, which does not lock
- The action specified in
Stream.forEachis required to be non-interfering whileIterable.forEachis allowed to set values in the underlyingArrayListwithout problems.
- In Java, Iterators returned by Collection classes, e.g. ArrayList, HashSet, Vector, etc., are fail fast. This means that if you try to add() or remove() from the underlying data structure while iterating it, you get a
ConcurrentModificationException.
https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#fail-fast
More Info: