Perbedaan antara findAny () dan findFirst () di Java 8

90

Saya sedikit bingung antara Stream#findAny()dan Stream#findFirst()tentang StreamAPI di Java 8.

Apa yang saya pahami adalah bahwa keduanya akan mengembalikan elemen pertama yang cocok dari aliran, misalnya, bila digunakan bersama dengan filter?

Jadi, mengapa dua metode untuk tugas yang sama? Apakah saya melewatkan sesuatu?

Mandeep Rajpal
sumber

Jawaban:

92

Apa yang saya pahami adalah bahwa keduanya akan mengembalikan elemen pertama yang cocok dari aliran, misalnya, bila digunakan dalam hubungannya dengan filter?

Itu tidak benar. Menurut javadoc, Stream#findAny():

Menampilkan Optional<T>penjelasan beberapa elemen aliran, atau kosong Optional<T>jika aliran kosong. Perilaku operasi ini secara eksplisit tidak deterministik; bebas memilih elemen apa pun di aliran. Ini untuk memungkinkan kinerja maksimal dalam operasi paralel;

sementara Stream.findFirst()akan mengembalikan Optional<T>deskripsi secara ketat elemen pertama dari aliran. The Streamkelas tidak memiliki .findOne()metode, jadi saya kira Anda berarti .findFirst().

Konstantin Yovkov
sumber
Saya masih tidak mengerti, jadi apa yang Anda katakan adalah bahkan setelah filterditerapkan, findAnydapat mengembalikan elemen apa pun, termasuk yang tidak cocok dengan filter yang diterapkan?
Koray Tugay
@KorayTugay - Tidak, setelah filter, elemen tersisa apa pun yang ada, findAnydapat mengembalikan elemen apa pun dari itu dalam (semacam) acak, khususnya dalam operasi aliran paralel
KrishPrabakar
46

Tidak, keduanya tidak akan mengembalikan elemen pertama Arus.

Dari Stream.findAny()(penekanan saya):

Menampilkan Optionalpenjelasan beberapa elemen aliran, atau kosong Optionaljika aliran kosong.

Ini adalah operasi terminal hubungan arus pendek.

Perilaku operasi ini secara eksplisit tidak deterministik; bebas memilih elemen apa pun di aliran . Ini untuk memungkinkan kinerja maksimal dalam operasi paralel; biayanya adalah beberapa pemanggilan pada sumber yang sama mungkin tidak memberikan hasil yang sama. (Jika menginginkan hasil yang stabil, gunakan findFirst()saja.)

Jadi sederhananya, mungkin atau mungkin tidak memilih elemen pertama dari Arus.

Dengan implementasi khusus Oracle saat ini, saya percaya bahwa itu akan mengembalikan elemen pertama dalam pipa non-paralel. Namun, dalam pipeline paralel, itu tidak selalu (dijalankan misalnya System.out.println(IntStream.range(0, 100).parallel().findAny());, dikembalikan OptionalInt[50]saat saya menjalankannya). Bagaimanapun, Anda tidak boleh mengandalkan itu.

Tunaki
sumber
16

findFirst mengembalikan elemen pertama aliran, tetapi findAny bebas memilih elemen apa pun di aliran.

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
Amir
sumber
1

dalam mode paralel urutan findAnytidak dijamin, tetapi findFirsttidak.

Saya menulis beberapa potongan kode untuk menunjukkan perbedaannya, kunjungi

jiahut
sumber
1

Dalam aliran findFirst dan findAny mengembalikan elemen pertama dan tidak mengeksekusi sisanya tetapi dalam parallelStream, tidak diperbolehkan untuk mengatakan urutan dan parallelStream mengeksekusi sisa koleksi.

Referensi

Waktu 1:25:00

emon
sumber
1

Saya hanya akan mengatakan bahwa waspadalah terhadap findFirst()Dan findAny()saat menggunakan.

Dari Javadoc mereka (di sini dan di sini ) kedua metode mengembalikan elemen arbitrer dari aliran - kecuali aliran memiliki urutan pertemuan , dalam hal ini findFirst()mengembalikan elemen pertama sementara findAny()akan mengembalikan elemen apa pun.

Misalkan kita memiliki listnama ISBN dan BUKU yang terdiri dari custom . Untuk skenario, lihat contoh ini:

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());
    }

Keluaran :Optional[Java in Action]

Ada beberapa skenario ketika nama Buku sama tetapi nomor ISBN berbeda, dalam hal ini penyortiran dan pencarian buku bisa sangat mirip findAny()dan akan memberikan hasil yang salah. Pikirkan skenario di mana 5 buku diberi nama "Referensi Java" tetapi memiliki nomor ISBN yang berbeda dan findFirst()buku berdasarkan nama akan menghasilkan sama seperti findAny().

Pikirkan skenario di mana:

 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 |
+-----+------------------+

di sini findFirst () dan findAny () akan memberikan hasil yang sama meskipun diurutkan di BookByName.

Artikel Rinci:

Vishwa Ratna
sumber
-1

Kapan Streamtidak berurutan, findFirst()dan findAny()sama. Tapi kalau Streamsudah dipesan, findAny()akan lebih baik.

logbasex
sumber
Ini salah Tidak satu pun dari metode ini yang "lebih baik", karena perilaku dan kasus penggunaannya sama sekali berbeda. Juga, apa yang Anda maksud dengan Streammakhluk yang "diperintahkan"? Itu selalu dipesan (operasi dijalankan pada yang diberikan Streamdalam urutan yang sama setiap kali tidak diparalelkan), tetapi mungkin tidak diurutkan oleh pengguna.
Jezor