การลดลงตามปกติหมายถึงการรวมสองค่าที่ไม่เปลี่ยนรูปเช่น int, double และอื่น ๆ และสร้างค่าใหม่ เป็นการลดที่ไม่เปลี่ยนรูป ในทางตรงกันข้ามวิธีการรวบรวมได้รับการออกแบบมาเพื่อกลายพันธุ์ภาชนะเพื่อสะสมผลที่ควรจะผลิต
เพื่อแสดงปัญหาลองสมมติว่าคุณต้องการบรรลุCollectors.toList()
โดยใช้การลดแบบง่ายๆ
List<Integer> numbers = stream.reduce(
new ArrayList<Integer>(),
(List<Integer> l, Integer e) -> {
l.add(e);
return l;
},
(List<Integer> l1, List<Integer> l2) -> {
l1.addAll(l2);
return l1;
});
Collectors.toList()
นี่คือเทียบเท่า List<Integer>
แต่ในกรณีนี้คุณกลายพันธุ์ ดังที่เราทราบว่าArrayList
ไม่ปลอดภัยต่อเธรดและไม่ปลอดภัยที่จะเพิ่ม / ลบค่าออกจากมันในขณะที่วนซ้ำดังนั้นคุณจะได้รับข้อยกเว้นพร้อมกันหรือข้อยกเว้นArrayIndexOutOfBoundsException
ชนิดใด ๆ (โดยเฉพาะอย่างยิ่งเมื่อทำงานแบบขนาน) เมื่อคุณอัปเดตรายการหรือ combiner พยายามที่จะรวมรายการเพราะคุณกำลังกลายพันธุ์รายการโดยการสะสม (เพิ่ม) จำนวนเต็มไป ถ้าคุณต้องการทำให้เธรดนี้ปลอดภัยคุณต้องผ่านรายการใหม่ทุกครั้งที่ทำให้ประสิทธิภาพลดลง
ในทางตรงกันข้ามการCollectors.toList()
ทำงานในลักษณะที่คล้ายกัน อย่างไรก็ตามมันรับประกันความปลอดภัยของด้ายเมื่อคุณสะสมค่าลงในรายการ จากเอกสารสำหรับcollect
วิธีการ :
ดำเนินการลดที่ไม่แน่นอนในองค์ประกอบของสตรีมนี้โดยใช้ Collector หากสตรีมเป็นแบบขนานและ Collector พร้อมกันและสตรีมไม่ได้เรียงลำดับหรือไม่ได้เรียงลำดับตัวสะสมจะทำการลดพร้อมกัน เมื่อดำเนินการแบบขนานผลลัพธ์ระหว่างกลางหลายรายการอาจถูกทำให้เป็นอินสแตนซ์เติมและผสานเพื่อรักษาความแยกของโครงสร้างข้อมูลที่ไม่แน่นอน ดังนั้นแม้ว่าจะดำเนินการแบบขนานพร้อมกับโครงสร้างข้อมูลที่ไม่ปลอดภัย (เช่น ArrayList) ไม่จำเป็นต้องทำการซิงโครไนซ์เพิ่มเติมสำหรับการลดแบบขนาน
ดังนั้นเพื่อตอบคำถามของคุณ:
เมื่อคุณจะใช้collect()
VS reduce()
?
ถ้าคุณมีค่าไม่เปลี่ยนรูปเช่นints
, doubles
, Strings
แล้วลดปกติทำงานได้ดี อย่างไรก็ตามหากคุณจำเป็นต้องreduce
พูดถึง a List
(โครงสร้างข้อมูลที่ไม่แน่นอน) คุณต้องใช้การลดที่ไม่แน่นอนกับcollect
วิธีการ