試驗了一下java stream中的findAny和findFirst,發現都返回了列表中的第一個元素。那么,這兩種方法的區別是什么呢?
查看了一下Java API document:
findFirst:
findFirst
Optional<T> findFirst()Returns an
Optionaldescribing the first element of this stream, or an emptyOptionalif the stream is empty. If the stream has no encounter order, then any element may be returned.This is a short-circuiting terminal operation.
Returns:
an
Optionaldescribing the first element of this stream, or an emptyOptionalif the stream is emptyThrows:
NullPointerException- if the element selected is null
顧名思義,即返回列表中的第一個元素。
這里的short-circuiting是指:有時候需要在遍歷中途停止操作,比如查找第一個滿足條件的元素或者limit操作。在Stream中short-circuiting操作有:anyMatch、allMatch、noneMatch、findFirst、findAny、limit,這些操作在Sink中都有一個變量來判斷是否短路,比如limit用的是m,match用的是stop,find用的是hasValue。
這里的terminal operation是指:一個終結操作,比如foreach,IntStream.sum
那么,findAny是什么呢?
findAny
Optional<T> findAny()Returns an
Optionaldescribing some element of the stream, or an emptyOptionalif the stream is empty.This is a short-circuiting terminal operation.
The behavior of this operation is explicitly nondeterministic(不確定的); it is free to select any element in the stream. This is to allow for maximal performance in parallel operations; the cost is that multiple invocations(調用) on the same source may not return the same result. (If a stable result is desired, use
findFirst()instead.)Returns:
an
Optionaldescribing some element of this stream, or an emptyOptionalif the stream is emptyThrows:
NullPointerException- if the element selected is nullSee Also:
可以看到findAny()操作,返回的元素是不確定的,對於同一個列表多次調用findAny()有可能會返回不同的值。使用findAny()是為了更高效的性能。如果是數據較少,串行地情況下,一般會返回第一個結果,如果是並行的情況,那就不能確保是第一個。比如下面的例子會隨機地返回OptionalInt[50]。
System.out.println(IntStream.range(0, 100).parallel().findAny());
讓我們來舉另外一個例子:
-
List<String> lst1 = Arrays.asList( "Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");
-
List<String> lst2 = Arrays.asList( "Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");
-
-
Optional<String> findFirst = lst1.parallelStream().filter(s -> s.startsWith( "D")).findFirst();
-
Optional<String> fidnAny = lst2.parallelStream().filter(s -> s.startsWith( "J")).findAny();
-
-
System.out.println(findFirst.get()); //總是打印出David
-
System.out.println(fidnAny.get()); //會隨機地打印出Jack/Jill/Julia
