Java 8'de findAny () ve findFirst () arasındaki fark


91

Ben küçük arasına karıştı Stream#findAny()ve Stream#findFirst()bir StreamJava 8'de API.

Anladığım şey, örneğin filtre ile birlikte kullanıldığında, her ikisinin de akıştan ilk eşleşen öğeyi döndüreceğidir?

Öyleyse, neden aynı görev için iki yöntem? Bir şey mi kaçırıyorum?

Yanıtlar:


94

Anladığım şey, her ikisinin de örneğin filtre ile birlikte kullanıldığında akıştan ilk eşleşen öğeyi döndüreceğidir?

Bu doğru değil. Javadoc'a göre Stream#findAny():

Akışın bazı öğelerini Optional<T>açıklayan bir öğeyi veya akış boşsa boş bir değeri döndürür Optional<T>. Bu işlemin davranışı açıkça belirleyici değildir; Akıştaki herhangi bir öğeyi seçmek ücretsizdir. Bu, paralel işlemlerde maksimum performansa izin vermek içindir;

while Stream.findFirst(), kesinlikle akışın ilk öğesini Optional<T>açıklayan bir döndürür . Sınıf yok Ne demek herhalde bu yüzden, yöntem .Stream.findOne().findFirst()


Hala anlamadım, bu yüzden ne diyorsunuz, a filteruygulandıktan sonra bile , uygulanan findAnyfiltreyle eşleşmeyenler dahil herhangi bir öğe döndürebilir mi?
Koray Tugay

@KorayTugay - Hayır, filtreden sonra, geri kalan elemanları, bu her ne olursa olsun, findAnyözellikle paralel akış işlemlerinde, rastgele (bir çeşit), bu herhangi bir öğe dönebilir
KrishPrabakar

46

Hayır, her ikisi de Akışın ilk öğesini döndürmeyecektir.

Gönderen Stream.findAny()(vurgu benim):

Akışın bazı öğesiniOptional açıklayan bir öğeyi veya akış boşsa boş bir değeri döndürür Optional.

Bu, kısa devre yapan bir terminal işlemidir.

Bu işlemin davranışı açıkça belirleyici değildir; Akıştaki herhangi bir öğeyi seçmek ücretsizdir . Bu, paralel işlemlerde maksimum performansa izin vermek içindir; maliyet, aynı kaynaktaki birden çok çağrının aynı sonucu döndürmemesidir. (Kararlı bir sonuç isteniyorsa findFirst()bunun yerine kullanın.)

Daha basit bir ifadeyle, Akışın ilk unsurunu seçebilir veya seçmeyebilir.

Oracle'a özgü mevcut uygulama ile, paralel olmayan bir boru hattındaki ilk öğeyi döndüreceğine inanıyorum. Bununla birlikte, paralel bir boru hattında, her zaman, örneğin

System.out.println(IntStream.range(0, 100).parallel().findAny());

çalıştırdığımda geri döndü OptionalInt[50]. Her neyse, buna güvenmemelisin.


17

findFirst, akışın ilk öğelerini döndürür, ancak findAny, akıştaki herhangi bir öğeyi seçmekte serbesttir.

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

2

paralel modda findAnysipariş garanti edilmez, ancak findFirstolur.

Farkı göstermek için biraz kod parçası yazdım, ziyaret edin


1

Akışta findFirst ve findAny ilk öğeyi döndürür ve geri kalanını çalıştırmaz, ancak parallelStream'de, order ve parallelStream'in koleksiyonun geri kalanını yürüttüğünü söylemek pek mümkün değildir.

Referans

Zaman 1:25:00


1

Ben sadece dikkat findFirst()ve findAny()kullanırken söyleyeceğim .

Javadoc'larından ( burada ve burada ) itibaren her iki yöntem de akıştan rastgele bir öğe döndürür - akışın bir karşılaşma sırası yoksa, bu durumda findFirst()ilk öğeyi findAny()döndürürken herhangi bir öğeyi döndürür.

Özel olarak listoluşan ISBN ve KİTAP adımız olduğunu varsayalım . Bir senaryo için şu örneğe bakın:

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

Çıktı :Optional[Java in Action]

Kitap adının aynı olduğu ancak ISBN numaralarının farklı olduğu senaryolar olabilir, bu durumda kitabı sıralamak ve bulmak çok benzer olabilir findAny()ve yanlış sonuç verir. 5 kitabın "Java Referansı" olarak adlandırıldığı, ancak farklı ISBN numaralarına sahip olduğu ve findFirst()ada göre kitabın aynı sonuca ulaşacağı bir senaryo düşünün findAny().

Aşağıdaki durumlarda bir senaryo düşünün:

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

burada findFirst () ve findAny () BookByName üzerinde sıralansa bile aynı sonucu verecektir .

Ayrıntılı Makale:


-1

Ne zaman Streamsırasızdır findFirst()ve findAny()aynıdır. Ama ne zaman Streamsipariş findAny()edilirse daha iyi olur.


Bu yanlış. Bu yöntemlerin hiçbiri "daha iyi" değildir, çünkü davranışları ve kullanım durumları tamamen farklıdır. Ayrıca, Stream"düzenli" olmaktan kastınız nedir? Her zaman sıralanır (işlemler, Streamparalelleştirilmediğinde her seferinde aynı sırayla yürütülür ), ancak belki de kullanıcıya göre sıralanmaz.
Jezor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.