1

According to JavaDocs the Stream map function takes a Function<? super T,? extends R> mapper as an argument.

The mapper parameter is described as:

a non-interfering, stateless function to apply to each element

I understand why stateless, but why Non-interfering?

Edit: Including Non-interfering JavaDoc link:

Streams enable you to execute possibly-parallel aggregate operations over a variety of data sources, including even non-thread-safe collections such as ArrayList. This is possible only if we can prevent interference with the data source during the execution of a stream pipeline. Except for the escape-hatch operations iterator() and spliterator(), execution begins when the terminal operation is invoked, and ends when the terminal operation completes. For most data sources, preventing interference means ensuring that the data source is not modified at all during the execution of the stream pipeline. The notable exception to this are streams whose sources are concurrent collections, which are specifically designed to handle concurrent modification. Concurrent stream sources are those whose Spliterator reports the CONCURRENT characteristic. Accordingly, behavioral parameters in stream pipelines whose source might not be concurrent should never modify the stream's data source. A behavioral parameter is said to interfere with a non-concurrent data source if it modifies, or causes to be modified, the stream's data source. The need for non-interference applies to all pipelines, not just parallel ones. Unless the stream source is concurrent, modifying a stream's data source during execution of a stream pipeline can cause exceptions, incorrect answers, or nonconformant behavior. For well-behaved stream sources, the source can be modified before the terminal operation commences and those modifications will be reflected in the covered elements. For example, consider the following code:

 List<String> l = new ArrayList(Arrays.asList("one", "two"));
 Stream<String> sl = l.stream();
 l.add("three");
 String s = sl.collect(joining(" "));

First a list is created consisting of two strings: "one"; and "two". Then a stream is created from that list. Next the list is modified by adding a third string: "three". Finally the elements of the stream are collected and joined together. Since the list was modified before the terminal collect operation commenced the result will be a string of "one two three". All the streams returned from JDK collections, and most other JDK classes, are well-behaved in this manner; for streams generated by other libraries, see Low-level stream construction for requirements for building well-behaved streams.

Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
jspek
  • 438
  • 3
  • 10
  • 6
    Imagine you’re streaming the elements of a List, and an intermediate function like a mapper calls `clear()` on the List. Or [Collections.shuffle](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#shuffle-java.util.List-). – VGR Jul 07 '17 at 20:12
  • Perfect example. – jspek Jul 07 '17 at 20:20
  • 2
    Since the "[non-interfering](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#NonInterference)" word in the javadoc you linked is actually a link *(like I just did it)*, did you click on it and read what the word "non-interfering" means? – Andreas Jul 07 '17 at 20:21
  • @Andreas OP is not asking what non-interference means, but why it's required on the behavioral argument of `map`. I admit that if you follow the link in the javadocs of `map`, apart from learning what non-interference actually is, you might also learn why it's required. Anyways, I'm almost sure this is a duplicate, I'm searching to mark it as one... – fps Jul 07 '17 at 20:48
  • @VGR answered the question. An example of where ConcurrentModificationException would be thrown is: `myList.stream().map(myStr->{myList.clear(); return myStr;}).forEach(System.out::println);` – jspek Jul 07 '17 at 20:52
  • @jspek That is true for non-concurrent sources i.e. `ArrayList`, you'll get a `ConcurrentModificationException`. However, you can avoid that exception if the source is i.e. a `ConcurrentHashMap` and you are streaming its `entrySet()`, but be ready to notice some nasty inconsistencies... – fps Jul 07 '17 at 20:57
  • @jspek I've closed this one since it looks like at exact duplicate... you can also read the comments there to see some great examples also – Eugene Jul 09 '17 at 09:45

0 Answers0