Java 8におけるfindAnyとfindFirstの違い

3276 ワード

Java streamのfindAnyとfindFirstを試してみると、リストの最初の要素が返されています.では、この2つの方法の違いは何でしょうか.
Java API documentを見てみました.
findFirst:
findFirst
Optional findFirst()

Returns an  Optional  describing the first element of this stream, or an empty  Optional  if 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  Optional  describing the first element of this stream, or an empty  Optional  if the stream is empty
Throws: 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 findAny()

Returns an  Optional  describing some element of the stream, or an empty  Optional  if 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  Optional  describing some element of this stream, or an empty  Optional  if the stream is empty
Throws: NullPointerException  - if the element selected is null
See Also: findFirst()
findAny()操作は、返される要素が不確定であり、同じリストに対してfindAny()を複数回呼び出すと異なる値が返される可能性があることがわかります.findAny()を使用するのは、より効率的なパフォーマンスのためです.データが少ない場合、シリアルの場合、通常は最初の結果が返され、パラレルの場合、最初の結果が確保されません.例えば次の例では、OptionalInt[50]がランダムに返される.
System.out.println(IntStream.range(0, 100).parallel().findAny());

別の例を挙げてみましょう
List lst1 = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");
List lst2 = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");

Optional findFirst = lst1.parallelStream().filter(s -> s.startsWith("D")).findFirst();
Optional fidnAny = lst2.parallelStream().filter(s -> s.startsWith("J")).findAny();

System.out.println(findFirst.get()); //     David
System.out.println(fidnAny.get()); //       Jack/Jill/Julia

参照リンク:
1. https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#findFirst--
2. https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#findAny--
3. https://stackoverflow.com/questions/35359112/difference-between-findany-and-findfirst-in-java-8