ความแตกต่างระหว่าง findAny () และ findFirst () ใน Java 8


91

ฉันสับสนเล็กน้อยระหว่างStream#findAny()และStream#findFirst()ของ StreamAPI ใน Java 8

สิ่งที่ฉันเข้าใจคือทั้งสองจะส่งคืนองค์ประกอบแรกที่ตรงกันจากสตรีมเช่นเมื่อใช้ร่วมกับตัวกรอง?

เหตุใดจึงมีสองวิธีสำหรับงานเดียวกัน? ฉันพลาดอะไรไปรึเปล่า?

คำตอบ:


94

สิ่งที่ฉันเข้าใจคือทั้งสองจะส่งคืนองค์ประกอบแรกที่ตรงกันจากสตรีมเช่นเมื่อใช้ร่วมกับตัวกรอง?

ที่ไม่เป็นความจริง. อ้างอิงจาก javadoc Stream#findAny():

ส่งกลับคำOptional<T>อธิบายองค์ประกอบบางส่วนของสตรีมหรือค่าว่าง Optional<T>หากสตรีมว่างเปล่า พฤติกรรมของการดำเนินการนี้ไม่แน่นอนอย่างชัดเจน สามารถเลือกองค์ประกอบใด ๆ ในสตรีมได้ฟรี เพื่อให้ได้ประสิทธิภาพสูงสุดในการทำงานแบบขนาน

ในขณะที่Stream.findFirst()จะส่งกลับคำOptional<T>อธิบายอย่างเคร่งครัดองค์ประกอบแรกของสตรีม Streamชั้นไม่ได้มีวิธีการดังนั้นฉันคิดว่าคุณหมายถึง.findOne().findFirst()


ฉันยังไม่เข้าใจดังนั้นสิ่งที่คุณกำลังพูดถึงแม้ว่าfilterจะใช้a ไปแล้วก็ตามfindAnyสามารถส่งคืนองค์ประกอบใด ๆ รวมทั้งที่ไม่ตรงกับตัวกรองที่ใช้?
Koray Tugay

@KorayTugay - ไม่หลังจากตัวกรององค์ประกอบใด ๆ ที่เหลืออยู่findAnyสามารถส่งคืนองค์ประกอบใด ๆ จากสิ่งนั้นใน (เรียงลำดับ) แบบสุ่มโดยเฉพาะอย่างยิ่งในการดำเนินการสตรีมคู่ขนาน
KrishPrabakar

46

ไม่ทั้งสองจะไม่ส่งคืนองค์ประกอบแรกของสตรีม

จากStream.findAny()(เน้นของฉัน):

ส่งกลับคำOptionalอธิบายองค์ประกอบบางส่วนของสตรีมหรือค่าว่างOptionalหากสตรีมว่างเปล่า

นี่คือการทำงานของเทอร์มินัลที่ลัดวงจร

พฤติกรรมของการดำเนินการนี้ไม่แน่นอนอย่างชัดเจน สามารถเลือกองค์ประกอบใด ๆ ในสตรีมได้ฟรี เพื่อให้ได้ประสิทธิภาพสูงสุดในการทำงานแบบขนาน ค่าใช้จ่ายคือการเรียกใช้หลายครั้งในแหล่งเดียวกันอาจไม่ส่งคืนผลลัพธ์เดียวกัน (หากต้องการผลลัพธ์ที่มั่นคงให้ใช้findFirst()แทน)

ดังนั้นเพื่อให้ง่ายขึ้นอาจเลือกองค์ประกอบแรกของสตรีมหรือไม่ก็ได้

ด้วยการใช้งานเฉพาะของ Oracle ในปัจจุบันฉันเชื่อว่าจะส่งคืนองค์ประกอบแรกในไปป์ไลน์ที่ไม่ขนานกัน อย่างไรก็ตามในท่อคู่ขนานจะไม่ดำเนินการเสมอไปเช่น

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

มันกลับมาOptionalInt[50]เมื่อฉันวิ่ง อย่างไรก็ตามคุณต้องไม่พึ่งพาสิ่งนั้น


17

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

2

ในโหมดคู่ขนานfindAnyไม่รับประกันคำสั่ง แต่findFirstไม่

ฉันเขียนข้อมูลโค้ดเพื่อแสดงความแตกต่างไปที่มัน


1

ในสตรีม findFirst และ findAny ส่งคืนองค์ประกอบแรกและไม่ดำเนินการส่วนที่เหลือ แต่ในแบบขนานสตรีมจะไม่สามารถพูดได้ว่าคำสั่งและ parallelStream ดำเนินการส่วนที่เหลือของคอลเล็กชัน

ข้อมูลอ้างอิง

เวลา 01:25:00 น


1

ฉันจะบอกว่าระวังfindFirst()และfindAny()ในขณะที่ใช้

จาก Javadoc ของพวกเขา ( ที่นี่และที่นี่ ) ทั้งสองวิธีจะส่งคืนองค์ประกอบที่กำหนดเองจากสตรีม - เว้นแต่สตรีมจะมีลำดับการเผชิญหน้าซึ่งในกรณีนี้findFirst()จะส่งคืนองค์ประกอบแรกในขณะที่findAny()จะส่งคืนองค์ประกอบใด ๆ

สมมติว่าเรามีlistISBN และชื่อหนังสือที่กำหนดเอง สำหรับสถานการณ์ดูตัวอย่างนี้:

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 เล่มที่มีชื่อ "Java อ้างอิง" แต่มีหมายเลข 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.