ฉันควรใช้ Java Collection ใด


127

ในคำถามนี้ฉันจะเลือกคอนเทนเนอร์ไลบรารีมาตรฐานใน C ++ 11 อย่างมีประสิทธิภาพได้อย่างไร เป็นผังงานที่มีประโยชน์เพื่อใช้เมื่อเลือกคอลเลกชัน C ++

ฉันคิดว่านี่เป็นแหล่งข้อมูลที่มีประโยชน์สำหรับผู้ที่ไม่แน่ใจว่าควรใช้คอลเลคชันใดดังนั้นฉันจึงพยายามค้นหาผังงานที่คล้ายกันสำหรับ Java และไม่สามารถทำได้

มีทรัพยากรและ "ข้อมูลสรุป" อะไรบ้างที่ช่วยให้ผู้คนเลือกคอลเล็กชันที่เหมาะสมเพื่อใช้เมื่อเขียนโปรแกรมใน Java ผู้คนรู้ได้อย่างไรว่าควรใช้ List, Set และ Map อะไร


หนังสือ Java Generics and Collections (Naftalin & Wadler) มีบทเกี่ยวกับเรื่องนี้
Christophe Roussy

คำตอบ:


293

เนื่องจากฉันไม่พบผังงานที่คล้ายกันฉันจึงตัดสินใจสร้างด้วยตัวเอง

แผนภูมิการไหลนี้ไม่ได้ลองและครอบคลุมสิ่งที่ต้องการเข้าถึงข้อมูลให้ตรงกัน ฯลฯ ความปลอดภัยหัวข้อหรือคอลเลกชันเดิม แต่มันไม่ครอบคลุมมาตรฐาน 3 ชุด s 3 มาตรฐานแผนที่และมาตรฐาน 2 รายการ s

ป้อนคำอธิบายภาพที่นี่

ภาพนี้สร้างขึ้นสำหรับคำตอบนี้และได้รับอนุญาตภายใต้ใบอนุญาตCreative Commons Attribution 4.0 International การระบุแหล่งที่มาที่ง่ายที่สุดคือการเชื่อมโยงกับคำถามนี้หรือคำตอบนี้

แหล่งข้อมูลอื่น ๆ

น่าจะเป็นประโยชน์ในการอ้างอิงอื่น ๆ ส่วนใหญ่จะเป็นหน้าต่อไปนี้จากเอกสารของ Oracle ซึ่งจะอธิบายในแต่ละคอลเลกชัน

HashSet กับ TreeSet

มีรายละเอียดการอภิปรายว่าควรใช้เมื่อใดHashSetหรือTreeSetที่นี่: Hashset vs Treeset

ArrayList กับ LinkedList

การอภิปรายโดยละเอียด: เมื่อใดควรใช้ LinkedList ผ่าน ArrayList


ดี! แต่ผมจะต้องไม่เห็นด้วยกับคุณLinkedListเทียบกับArrayListการตัดสินใจ อันดับแรกหากรายการมีขนาดที่สำคัญLinkedListควรเลือกใช้ LinkedListมีค่าใช้จ่ายต่อองค์ประกอบดังนั้นจึงแย่ลงอย่างไม่มีอาการในแง่ของการใช้หน่วยความจำมากกว่าArrayListไฟล์. นอกจากนี้หากการเข้าถึงส่วนใหญ่อยู่ที่ส่วนท้ายของรายการArrayListจะดีกว่าเนื่องจากให้การเข้าถึงองค์ประกอบแบบสุ่มเวลาคงที่ การเข้าถึงnองค์ประกอบที่สามของ a LinkedListเป็นการO(n)ดำเนินการ ... ในความเป็นจริงการตัดสินใจที่จะใช้รายการที่เชื่อมโยงสวยมากควรเสมอเป็น "no."
Matt Ball

2
@MattBall ฉันเห็นด้วยกับคุณมากที่สุด อย่างไรก็ตาม Java LinkedListเป็นรายการที่เชื่อมโยงสองครั้งดังนั้นการเข้าถึงเมื่อเริ่มต้นและสิ้นสุดจึงทำได้รวดเร็ว คุณจะสังเกตได้ว่าสาขาข้างต้นคำถามทั้งสามต้องตอบว่าใช่ก่อนที่ฉันจะแนะนำให้ใช้LinkedList- ดังนั้นฉันเห็นด้วยกับคุณว่าในกรณีส่วนใหญ่คำตอบคือไม่ สิ่งเช่นคิวและ dequeues LinkedListที่คุณมีอย่างต่อเนื่องเพิ่มและลบสิ่งจากปลายของพื้นที่รายการดีกรณีการใช้งานสำหรับ
Tim B

การใช้หน่วยความจำ @MattBall เป็นสถานการณ์ที่ยุ่งยากกว่ามากในขณะที่LinkedListใช้หน่วยความจำต่อองค์ประกอบมากขึ้น ... ArrayListไม่เคยปล่อยหน่วยความจำ นั่นหมายความว่าหากคุณมีรายการที่บางครั้งมีขนาดใหญ่ขึ้น แต่มักมีขนาดเล็กArrayListจะทำให้ประสิทธิภาพของหน่วยความจำแย่ลง ค่าใช้จ่ายของหน่วยความจำListมักจะมีขนาดเล็ก (แม้ว่าจะไม่เสมอไป) เมื่อเทียบกับองค์ประกอบที่มีอยู่เช่นกัน
Tim B

Map<K,V>ไม่ใช่ส่วนหนึ่งของjava.util.collection
Mehraj Malik

@MehrajMalik อืมการติดฉลากคลุมเครือฉันเห็นด้วย ฉันหมายถึง Collection ภายใน java.util เช่น java.util * ใส่ชื่อคอลเลคชันที่นี่ *
Tim B

66

สรุปคอลเล็กชันหลักที่ไม่เกิดขึ้นพร้อมกันและไม่ซิงโครไนซ์

Collection: อินเทอร์เฟซที่แสดง "กระเป๋า" ของสิ่งของที่ไม่เรียงลำดับเรียกว่า "องค์ประกอบ" องค์ประกอบ "ถัดไป" ไม่ได้กำหนด (แบบสุ่ม)

  • Set: อินเทอร์เฟซที่แสดงถึงCollectionโดยไม่มีรายการที่ซ้ำกัน
    • HashSet: SetสนับสนุนโดยกHashtable. การใช้หน่วยความจำที่เร็วที่สุดและน้อยที่สุดเมื่อสั่งซื้อไม่สำคัญ
    • LinkedHashSet: การHashSetด้วยนอกเหนือจากรายการที่เชื่อมโยงกับองค์ประกอบร่วมในการสั่งซื้อแทรก องค์ประกอบ "ถัดไป" คือองค์ประกอบที่แทรกล่าสุดถัดไป
    • TreeSet: Setองค์ประกอบที่เรียงลำดับโดยComparator(โดยทั่วไปแล้วการเรียงลำดับตามธรรมชาติ ) การใช้หน่วยความจำช้าที่สุดและมากที่สุด แต่จำเป็นสำหรับการสั่งซื้อโดยใช้ตัวเปรียบเทียบ
    • EnumSet: การSetปรับแต่งที่รวดเร็วและมีประสิทธิภาพอย่างมากสำหรับประเภท enum เดียว
  • List: อินเทอร์เฟซที่แสดงถึงCollectionองค์ประกอบที่มีการเรียงลำดับและแต่ละองค์ประกอบมีดัชนีตัวเลขแทนตำแหน่งโดยที่ศูนย์เป็นองค์ประกอบแรกและ(length - 1)เป็นองค์ประกอบสุดท้าย
    • ArrayList: Listได้รับการสนับสนุนจากอาร์เรย์โดยที่อาร์เรย์มีความยาว (เรียกว่า "ความจุ") ซึ่งอย่างน้อยก็มีขนาดใหญ่เท่ากับจำนวนองค์ประกอบ ("ขนาด" ของรายการ) เมื่อขนาดเกินความจุ (เมื่อ(capacity + 1)-thองค์ประกอบที่จะถูกเพิ่ม) อาร์เรย์ถูกสร้างด้วยกำลังการผลิตใหม่ของ(new length * 1.5)การพักผ่อนหย่อนใจ --This System.arrayCopy()เป็นไปอย่างรวดเร็วเนื่องจากใช้ การลบและการแทรก / เพิ่มองค์ประกอบจำเป็นต้องมีการเลื่อนองค์ประกอบที่อยู่ใกล้เคียงทั้งหมด (ทางด้านขวา) เข้าหรือออกจากช่องว่างนั้น การเข้าถึงองค์ประกอบใด ๆ ทำได้อย่างรวดเร็วเนื่องจากต้องใช้การคำนวณ(element-zero-address + desired-index * element-size)เพื่อค้นหาตำแหน่งเท่านั้น ในสถานการณ์ส่วนใหญ่ an ArrayListเป็นที่ต้องการมากกว่าไฟล์LinkedList.
    • LinkedList: Listได้รับการสนับสนุนจากชุดของวัตถุแต่ละชิ้นเชื่อมโยงกับเพื่อนบ้าน "ก่อนหน้า" และ "ถัดไป" LinkedListนี้ยังมีและQueue Dequeการเข้าถึงองค์ประกอบทำได้โดยเริ่มจากองค์ประกอบแรกหรือองค์ประกอบสุดท้ายและข้ามไปจนกว่าจะถึงดัชนีที่ต้องการ การแทรกและการลบเมื่อถึงดัชนีที่ต้องการผ่านการข้ามผ่านเป็นเรื่องเล็กน้อยของการทำแผนที่ใหม่เฉพาะลิงก์เพื่อนบ้านที่ชี้ไปยังองค์ประกอบใหม่หรือข้ามองค์ประกอบที่ถูกลบในขณะนี้
  • Map: อินเทอร์เฟซแสดงCollectionตำแหน่งที่แต่ละองค์ประกอบมี "คีย์" ที่ระบุ - แต่ละองค์ประกอบเป็นคู่คีย์ - ค่า
    • HashMap: Mapที่ซึ่งคีย์ไม่เรียงลำดับและสำรองโดยไฟล์Hashtable.
    • LinkedhashMap: กุญแจจะได้รับคำสั่งจากคำสั่งแทรก
    • TreeMap: Mapตำแหน่งที่คีย์ถูกเรียงลำดับโดยComparator(โดยทั่วไปแล้วการเรียงลำดับตามธรรมชาติ)
  • Queue: อินเทอร์เฟซที่แสดงถึงCollectionตำแหน่งที่องค์ประกอบโดยทั่วไปถูกเพิ่มลงในปลายด้านหนึ่งและลบออกจากอีกด้านหนึ่ง (FIFO: เข้าก่อนก่อนออก)
  • Stack: อินเทอร์เฟซที่แสดงถึงCollectionตำแหน่งที่องค์ประกอบโดยทั่วไปมีทั้งเพิ่ม (ผลัก) และลบ (โผล่) จากจุดสิ้นสุดเดียวกัน (LIFO: last-in, first-out)
  • Deque: ย่อมาจาก "double ended que" โดยทั่วไปออกเสียงว่า "สำรับ" รายการที่เชื่อมโยงซึ่งโดยทั่วไปจะเพิ่มและอ่านจากปลายด้านใดด้านหนึ่งเท่านั้น (ไม่ใช่ตรงกลาง)

ไดอะแกรมคอลเลกชันพื้นฐาน:

แผนภาพ

การเปรียบเทียบการแทรกองค์ประกอบด้วยArrayListและLinkedList:

แผนภาพ


2
ดีที่สุดในช่วงฤดูร้อนสั้น ๆ ที่สามารถไปที่ไหนก็ได้ :)
roottraveller

11

แม้แต่ภาพที่เรียบง่ายกว่าก็อยู่ที่นี่ ตั้งใจง่าย!

  1. คอลเล็กชันคืออะไรก็ได้ที่เก็บข้อมูลที่เรียกว่า "องค์ประกอบ" (ประเภทเดียวกัน) ไม่มีอะไรที่เจาะจงมากขึ้นที่จะสันนิษฐาน

  2. รายการคือชุดข้อมูลที่จัดทำดัชนีโดยแต่ละองค์ประกอบมีดัชนี บางอย่างเช่นอาร์เรย์ แต่ยืดหยุ่นกว่า

    ข้อมูลในรายการจะจัดลำดับการแทรก

    การดำเนินการทั่วไป: รับองค์ประกอบที่ n

  3. ชุดคือถุงขององค์ประกอบแต่ละองค์ประกอบเพียงครั้งเดียว (องค์ประกอบมีความโดดเด่นโดยใช้equals()วิธีการของพวกเขา

    ข้อมูลในชุดจะถูกจัดเก็บไว้เป็นส่วนใหญ่เพื่อให้ทราบว่ามีข้อมูลอะไรบ้าง

    การดำเนินการทั่วไป: บอกว่ามีองค์ประกอบอยู่ในรายการหรือไม่

  4. แผนที่เป็นสิ่งที่คล้ายกับรายการ แต่แทนที่จะเข้าถึงองค์ประกอบด้วยดัชนีจำนวนเต็มคุณจะเข้าถึงองค์ประกอบเหล่านี้ด้วยคีย์ซึ่งก็คือวัตถุใด ๆ เช่นเดียวกับอาร์เรย์ใน PHP :)

    ข้อมูลในแผนที่สามารถค้นหาได้ด้วยคีย์

    การดำเนินการทั่วไป: รับองค์ประกอบด้วย ID (โดยที่ ID เป็นประเภทใดก็ได้ไม่เพียง แต่intในกรณีของ List)

ความแตกต่าง

  • ชุดที่ตั้งและแผนที่ในชุดคุณค้นหาข้อมูลด้วยตัวเองในขณะที่ในแผนที่โดยสำคัญของพวกเขา

  • รายการและแผนที่: ในรายการคุณเข้าถึงองค์ประกอบตามintดัชนี (ตำแหน่งในรายการ) ในขณะที่อยู่ในแผนที่โดยใช้คีย์ของระบบปฏิบัติการประเภทใดก็ได้ (โดยทั่วไปคือ ID)

  • รายการและชุด: ในรายการองค์ประกอบจะถูกผูกไว้ตามตำแหน่งและสามารถทำซ้ำได้ในขณะที่ในตั้งค่าองค์ประกอบจะเป็นเพียง "ปัจจุบัน" (pr not present) และไม่ซ้ำกัน (ตามความหมายequals()หรือcompareTo()สำหรับSortedSet)


1

เป็นเรื่องง่าย: หากคุณต้องการจัดเก็บค่าที่มีคีย์ที่แมปไว้ให้ไปที่ส่วนต่อประสานแผนที่มิฉะนั้นให้ใช้รายการสำหรับค่าที่อาจซ้ำกันและสุดท้ายใช้อินเทอร์เฟซ Set หากคุณไม่ต้องการให้ค่าซ้ำกันในคอลเล็กชันของคุณ

นี่คือคำอธิบายที่สมบูรณ์http://javatutorial.net/choose-the-right-java-collectionรวมถึงผังงาน ฯลฯ


1

แผนที่

หากเลือก a Mapฉันทำตารางนี้เพื่อสรุปคุณสมบัติของการใช้งานแต่ละรายการที่มาพร้อมกับ Java 11

ตารางการใช้งานแผนที่ใน Java 11 เปรียบเทียบคุณสมบัติต่างๆ



-2

ฉันควรใช้ Java Collection ใด

ขึ้นอยู่กับว่าคุณกำลังพยายามแก้ไขปัญหาอะไรหรือมีข้อกำหนดอะไรบ้าง

ตัวอย่าง :

  1. คุณต้องการจัดเรียงองค์ประกอบในขณะที่จัดเก็บหรือไม่? HashSet
  2. คุณต้องการจัดเก็บคู่ (Key, Value) ไว้หรือไม่? HashMap
  3. คุณต้องการจัดลำดับองค์ประกอบเมื่อแทรกเพื่อรักษาไว้หรือไม่? ArrayList, LinkedList
  4. คุณต้องการให้เรียงคีย์ในคู่ (คีย์ค่า) หรือไม่? - ข้อความที่แข็งแกร่ง
  5. คุณต้องการติดตั้ง Stack เพื่อแก้ปัญหาของคุณหรือไม่? - กอง
  6. คุณต้องการเข้าถึง FIFO (ก่อนเข้าก่อนออก) หรือไม่? - คิว
  7. คุณต้องการจัดเก็บเฉพาะองค์ประกอบ UNIQUE หรือไม่? - แฮชเซ็ต
  8. คุณต้องการอนุญาตให้คีย์เป็น "Null" ในขณะที่จัดเก็บ (Key, Value) หรือไม่ - HashMap
  9. คุณต้องการไม่มีค่า NULL สำหรับคู่ (Key, Value) หรือไม่? HashTable

ถึงแม้จะมีข้อความที่แข็งแกร่งในข้อ 4 แทนที่ด้วยการพูด, ConcurrentSkipListMap (K, V)สิ่งที่ไม่คำตอบนี้เพิ่มทิมบีกราฟการตัดสินใจเพื่อ aliteralmind ของ"คำอธิบายสั้นรายการ" ?
greybeard

จุดแรกของคุณ HashSet จะไม่จัดเรียงข้อมูลแม้ว่าจะไม่มีการรักษาลำดับการแทรก คุณควรเปลี่ยนด้วย TreeSet
Saurabh Mishra
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.