Java 8でのfindAny()とfindFirst()の違い


90

Java8のAPIStream#findAny()Stream#findFirst()の間で少し混乱してい Streamます。

私が理解したのは、たとえば、フィルターと組み合わせて使用​​した場合、両方がストリームから最初に一致した要素を返すということです。

では、なぜ同じタスクに2つの方法があるのでしょうか。私は何かが足りないのですか?

回答:


92

私が理解したのは、たとえば、フィルターと組み合わせて使用​​した場合、両方がストリームから最初に一致した要素を返すということです。

それは真実ではない。javadocによると、Stream#findAny()

ストリームの一部の要素を Optional<T>説明するものを返しますOptional<T>。ストリームが空の場合は空を返します。この操作の動作は明らかに非決定的です。ストリーム内の任意の要素を自由に選択できます。これは、並列操作で最大のパフォーマンスを実現するためです。

whileStream.findFirst()は、ストリームの最初の要素Optional<T>厳密に記述したものを返します。Streamクラスが持っていない.findOne()私はあなたが意味するものと仮定して、方法を.findFirst()


私はまだ理解していないので、あなたが言っていることは、afilterが適用された後でも、適用されfindAnyたフィルターと一致しない要素を含め、任意の要素を返すことができますか?
Koray Tugay

@ KorayTugay-いいえ、フィルターの後、残りの要素が何であれfindAny、特に並列ストリーム操作では、ランダムな(一種の)要素から任意の要素を返すことができます
KrishPrabakar

46

いいえ、どちらもストリームの最初の要素を返しません。

からStream.findAny()(強調鉱山):

ストリームの一部の要素Optional説明するものを返しますOptional。ストリームが空の場合は空を返します。

これは短絡端子操作です。

この操作の動作は明らかに非決定的です。ストリーム内の任意の要素を自由に選択できます。これは、並列操作で最大のパフォーマンスを実現するためです。コストは、同じソースで複数の呼び出しが同じ結果を返さない可能性があることです。(安定した結果が必要な場合は、findFirst()代わりに使用してください。)

つまり、簡単に言うと、ストリームの最初の要素を選択する場合と選択しない場合があります。

現在のOracle固有の実装では、非並列パイプラインの最初の要素が返されると思います。ただし、並列パイプラインでは、常にそうなるとは限りません(たとえばSystem.out.println(IntStream.range(0, 100).parallel().findAny());、実行すると返されOptionalInt[50]ます)。とにかく、あなたはそれに頼ってはいけませ


16

findFirstはストリームの最初の要素を返しますが、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()); //Always print David
System.out.println(fidnAny.get()); //Print Jack/Jill/Julia :behavior of this operation is explicitly nondeterministic


1

ストリームfindFirstとfindAnyは最初の要素を返し、残りを実行しませんが、parallelStreamでは、順序を言うことはできず、parallelStreamはコレクションの残りを実行します。

参照

時間1:25:00


1

私はただの気をつけろと言うだろうfindFirst()findAny()使用している間。

Javadoc(ここここ)からのように、両方のメソッドはストリームから任意の要素を返します–ストリームに遭遇順序がない限り、この場合findFirst()、最初の要素を返し、findAny()任意の要素を返します。

listISBNとBOOK名で構成されるカスタムがあるとします。シナリオについては、次の例を見てください。

public class Solution {
   private Integer ISBN;
   private String BookName;

public Solution(int i, String string) {
    ISBN =i;
    BookName = string;
}
//getters and setters
}

public static void main(String[] args) {
        List<Solution> Library = Arrays.asList(new Solution(12,"Java in Action"),new Solution(13,"Java 8"),new Solution(15,"Java 8 Features"),new Solution(16,"Java in Action"));
 System.out.println(Library.stream()
        .map(p->p.getBookName())
        .sorted(Comparator.reverseOrder())
        .findFirst());
    }

出力Optional[Java in Action]

書籍名は同じでもISBN番号が異なる場合があります。その場合、書籍の並べ替えと検索は非常に似ている可能性がfindAny()あり、間違った結果になります。5冊の本に「JavaReference」という名前が付いているが、ISBN番号が異なりfindFirst()、名前による本の結果がと同じになるシナリオを考えてみてくださいfindAny()

次のようなシナリオを考えてみてください。

 ISBN    Name Of book
+-----+------------------+
| 100 | Java-8 in Action |
+-----+------------------+
| 101 | Java-8 in Action |
+-----+------------------+
| 102 | Java-8 in Action |
+-----+------------------+
| 103 | Java-8 in Action |
+-----+------------------+
| 104 | Java-8 in Action |
+-----+------------------+

ここで、findFirst()とfindAny()は、BookByNameで並べ替えても同じ結果になります。

詳細記事:


-1

ときはStream順不同で、findFirst()かつfindAny()同じです。しかし、Stream注文されたときは、findAny()より良いでしょう。


これは正しくありません。これらの方法は、動作とユースケースが完全に異なるため、どちらも「優れた」ものではありません。また、Stream「注文」されるとはどういう意味ですか?常に順序付けられていますが(Stream並列化されていない場合は毎回同じ順序で操作が実行されます)、ユーザーによって並べ替えられていない可能性があります。
Jezor
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.