จะเข้าใจวิธีการรวบรวม Java 8 Stream นี้ได้อย่างไร?


12

ฉันพยายามแปลง int เป็น List และใช้เส้นทางที่ไม่คุ้นเคยในการใช้ Java 8 Stream และคิดสิ่งนี้ขึ้นมา

Arrays.stream(arr).boxed().collect(Collectors.toList());

ฉันยังคงมีปัญหาในการเข้าใจบรรทัดนี้ส่วนใหญ่

  1. เหตุใดCollectors.toList()ในกรณีนี้จึงส่งคืนอินเตอร์เฟสที่ArrayList<Integer>ใช้งาน Listทำไมไม่LinkedList<Integer>หรือคลาสทั่วไปอื่น ๆ ที่สอดคล้องกับListอินเตอร์เฟส? ฉันไม่พบสิ่งใดเกี่ยวกับเรื่องนี้ยกเว้นการกล่าวถึง ArrayList สั้น ๆที่นี่ในส่วน API Notes

  2. แผงด้านซ้าย หมายถึงอะไร เห็นได้ชัดว่าเป็นประเภทผลตอบแทนทั่วไป ( ในรหัสของฉันที่นี่) และฉันคิดว่าเป็นอาร์กิวเมนต์ประเภททั่วไปของวิธีการ แต่พวกเขาจะระบุได้อย่างไร ผมมองเข้าไปสะสมอินเตอร์เฟซ doc และไม่สามารถที่จะดูดซึมได้ป้อนคำอธิบายรูปภาพที่นี่ Stream.collect()RArrayList<Integer><R, A>


2
1. ใช้รายการจริงภายใต้ประทุนอย่างชัดเจน แต่มันจะไม่ฉลาดนักสำหรับ API ที่จะเปิดเผยประเภทรายการที่แท้จริง ตั้งแต่นั้นมาพวกเขาไม่สามารถเปลี่ยนการใช้งานได้อีกต่อไปในอนาคต โดยทั่วไปมักเป็นความคิดที่ดีที่จะแสดงเฉพาะอินเตอร์เฟสและไม่ต้องเป็นชนิดข้อมูลอ้างอิงจริง 2. Rเป็นประเภททั่วไปของประเภทผลลัพธ์ Aประเภททั่วไปของประเภทการสะสมขั้นกลางของนักสะสม นั่นคือรายละเอียดการนำไปปฏิบัติเกี่ยวกับวิธีการทำงานของตัวสะสมมันแบ่งและพิชิตสำหรับการประมวลผลแบบขนาน
Zabuzard

10
คุณแทบจะไม่เคยจริงต้องการ LinkedList มีทวีตของ Josh Blochโดยพูดว่า "ฉันเขียนมันและฉันไม่เคยใช้เลย"
Andy Turner

4
"ทำไมCollectors.toList()ในกรณีนี้กลับArrayList<Integer>"ArrayListมันอาจจะไม่กลับ Listการดำเนินงานจะไม่ได้กำหนดดังนั้นคุณจึงไม่สามารถพึ่งพาสิ่งที่ดำเนินการก็จะส่งกลับ ตามที่javadocพูดว่า: " ไม่มีการรับประกันประเภท , ความผันแปร, ความต่อเนื่องของอนุกรมหรือความปลอดภัยของเธรดของรายการที่ส่งคืน"
Andreas

3
และtoList()จะไม่ส่งคืน a ArrayListหรือList- กำลังส่งคืนCollectorซึ่งในที่สุดจะสร้างและส่งคืนList- ในเอกสารระบุ: "... ไม่มีการรับประกันประเภท , ความผันแปร, ความต่อเนื่องของอนุกรมหรือความปลอดภัยของเธรดที่ส่งคืน; หากต้องการการควบคุมมากกว่ารายการที่ถูกส่งคืนให้ใช้ toCollection (ผู้ผลิต) .... "
user85421-Banned

คำตอบ:


18
  1. เป็นการเริ่มต้นใช้งาน ArrayListใช้แล้วเพราะจะดีที่สุดในกรณีใช้งานส่วนใหญ่ แต่ถ้ามันไม่เหมาะกับคุณคุณสามารถกำหนดตัวสะสมของคุณเองและจัดหาโรงงานสำหรับCollectionคุณตามที่คุณต้องการ:

    Arrays.stream(arr).boxed().collect(toCollection(LinkedList::new));
  2. ใช่AและRเป็นพารามิเตอร์ทั่วไปของวิธีนี้Rคือประเภทส่งคืนTเป็นประเภทอินพุตและAเป็นสื่อกลางที่ปรากฏในกระบวนการทั้งหมดของการรวบรวมองค์ประกอบ (อาจไม่สามารถมองเห็นได้และไม่เกี่ยวข้องกับฟังก์ชั่นนี้) จุดเริ่มต้นของCollectorjavadocกำหนดประเภทเหล่านั้น (พวกเขามีความสอดคล้องกันในเอกสารทั้งหมด):

    T - ประเภทขององค์ประกอบอินพุตเพื่อการดำเนินการลด
    A - ประเภทการสะสมที่ไม่แน่นอนของการดำเนินการลด (มักจะซ่อนอยู่ในรายละเอียดการดำเนินการ)
    R - ประเภทผลลัพธ์ของการดำเนินการลด


โอเคฉันเห็นแล้ว ฉันเดาว่าฉันควรจะติดList<Integer> myList = Arrays.stream(arr).boxed().collect(Collectors.toList());และเรียกเฉพาะวิธีการประกาศในรายการอินเตอร์เฟซตาม myList ไม่เช่นนั้นฉันอาจเสี่ยงต่อการตัดสินใจของตนเองถ้า Oracle ตัดสินใจเปลี่ยนการใช้งานเริ่มต้นใน Java8u1024 หรือ 15
user3207158

2
@ user3207158 วิธีการคืนค่า a Listดังนั้นการใช้งานใด ๆ ก็ตามจะมีพฤติกรรมเหมือนกัน ไม่น่าเป็นไปได้ที่อินเทอร์เฟซจะถูกเปลี่ยนเป็นจาวาเวอร์ชันใหม่
Andronicus

1
  1. เหตุใด Collector.toList () ในกรณีนี้จึงส่งคืน ArrayList ที่ใช้อินเตอร์เฟสรายการ

ArrayListในฐานะที่เป็นความหมายที่แสดงให้เห็นวิธีการที่จะส่งกลับการดำเนินงานของนักสะสมกับซัพพลายเออร์เป็น ดังนั้นมันชัดเจนมากจากคำนิยามวิธีการด้านล่างที่Collectors.toListมักจะส่งกลับ ArrayList Collector ( While it's arguable why toList not toArrayList word is used in method name)

public static <T>
    Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
    }
  1. แผงด้านซ้าย<R, A> R collect(Collector<? super T, A, R> collector)หมายถึงอะไร

หากคุณอ้างถึงความคิดเห็นของเอกสารมันกล่าวถึงประเภททั่วไปเหล่านี้อย่างถูกต้อง:

/*
      @param <R> the type of the result
      @param <A> the intermediate accumulation type of the {@code Collector}
      @param collector the {@code Collector} describing the reduction
      @return the result of the reduction
*/
 <R, A> R collect(Collector<? super T, A, R> collector);

ขอบคุณครับ คุณได้รับซอร์สโค้ดของที่ไหนCollectors.toList()(ตัวอย่างข้อมูลแรก) มันเป็น openjdk?
user3207158

1
No! ฉันได้ดาวน์โหลดซอร์สโค้ดใน intelli j ของฉัน
Vinay Prajapati
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.