ฉันสับสนเล็กน้อยระหว่างStream#findAny()และStream#findFirst()ของ StreamAPI ใน Java 8
สิ่งที่ฉันเข้าใจคือทั้งสองจะส่งคืนองค์ประกอบแรกที่ตรงกันจากสตรีมเช่นเมื่อใช้ร่วมกับตัวกรอง?
เหตุใดจึงมีสองวิธีสำหรับงานเดียวกัน? ฉันพลาดอะไรไปรึเปล่า?
ฉันสับสนเล็กน้อยระหว่างStream#findAny()และStream#findFirst()ของ StreamAPI ใน Java 8
สิ่งที่ฉันเข้าใจคือทั้งสองจะส่งคืนองค์ประกอบแรกที่ตรงกันจากสตรีมเช่นเมื่อใช้ร่วมกับตัวกรอง?
เหตุใดจึงมีสองวิธีสำหรับงานเดียวกัน? ฉันพลาดอะไรไปรึเปล่า?
คำตอบ:
สิ่งที่ฉันเข้าใจคือทั้งสองจะส่งคืนองค์ประกอบแรกที่ตรงกันจากสตรีมเช่นเมื่อใช้ร่วมกับตัวกรอง?
ที่ไม่เป็นความจริง. อ้างอิงจาก javadoc Stream#findAny():
ส่งกลับคำ
Optional<T>อธิบายองค์ประกอบบางส่วนของสตรีมหรือค่าว่างOptional<T>หากสตรีมว่างเปล่า พฤติกรรมของการดำเนินการนี้ไม่แน่นอนอย่างชัดเจน สามารถเลือกองค์ประกอบใด ๆ ในสตรีมได้ฟรี เพื่อให้ได้ประสิทธิภาพสูงสุดในการทำงานแบบขนาน
ในขณะที่Stream.findFirst()จะส่งกลับคำOptional<T>อธิบายอย่างเคร่งครัดองค์ประกอบแรกของสตรีม Streamชั้นไม่ได้มีวิธีการดังนั้นฉันคิดว่าคุณหมายถึง.findOne().findFirst()
findAnyสามารถส่งคืนองค์ประกอบใด ๆ จากสิ่งนั้นใน (เรียงลำดับ) แบบสุ่มโดยเฉพาะอย่างยิ่งในการดำเนินการสตรีมคู่ขนาน
ไม่ทั้งสองจะไม่ส่งคืนองค์ประกอบแรกของสตรีม
จากStream.findAny()(เน้นของฉัน):
ส่งกลับคำ
Optionalอธิบายองค์ประกอบบางส่วนของสตรีมหรือค่าว่างOptionalหากสตรีมว่างเปล่านี่คือการทำงานของเทอร์มินัลที่ลัดวงจร
พฤติกรรมของการดำเนินการนี้ไม่แน่นอนอย่างชัดเจน สามารถเลือกองค์ประกอบใด ๆ ในสตรีมได้ฟรี เพื่อให้ได้ประสิทธิภาพสูงสุดในการทำงานแบบขนาน ค่าใช้จ่ายคือการเรียกใช้หลายครั้งในแหล่งเดียวกันอาจไม่ส่งคืนผลลัพธ์เดียวกัน (หากต้องการผลลัพธ์ที่มั่นคงให้ใช้findFirst()แทน)
ดังนั้นเพื่อให้ง่ายขึ้นอาจเลือกองค์ประกอบแรกของสตรีมหรือไม่ก็ได้
ด้วยการใช้งานเฉพาะของ Oracle ในปัจจุบันฉันเชื่อว่าจะส่งคืนองค์ประกอบแรกในไปป์ไลน์ที่ไม่ขนานกัน อย่างไรก็ตามในท่อคู่ขนานจะไม่ดำเนินการเสมอไปเช่น
System.out.println(IntStream.range(0, 100).parallel().findAny());
มันกลับมาOptionalInt[50]เมื่อฉันวิ่ง อย่างไรก็ตามคุณต้องไม่พึ่งพาสิ่งนั้น
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
ในโหมดคู่ขนานfindAnyไม่รับประกันคำสั่ง แต่findFirstไม่
ฉันเขียนข้อมูลโค้ดเพื่อแสดงความแตกต่างไปที่มัน
ในสตรีม findFirst และ findAny ส่งคืนองค์ประกอบแรกและไม่ดำเนินการส่วนที่เหลือ แต่ในแบบขนานสตรีมจะไม่สามารถพูดได้ว่าคำสั่งและ parallelStream ดำเนินการส่วนที่เหลือของคอลเล็กชัน
เวลา 01:25:00 น
ฉันจะบอกว่าระวัง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 ก็ตาม
Streamไม่เรียงลำดับเมื่อไหร่findFirst()และfindAny()เหมือนกัน แต่เมื่อStreamได้รับคำสั่งfindAny()จะดีกว่า.
Stream"ถูกสั่ง" หมายความว่าอย่างไร จะเรียงลำดับเสมอ (การดำเนินการจะดำเนินการตามที่กำหนดStreamในลำดับเดียวกันทุกครั้งเมื่อไม่ได้ขนานกัน) แต่อาจไม่ได้จัดเรียงโดยผู้ใช้
filterจะใช้a ไปแล้วก็ตามfindAnyสามารถส่งคืนองค์ประกอบใด ๆ รวมทั้งที่ไม่ตรงกับตัวกรองที่ใช้?