ทำไม java.util.Set จึงไม่ได้รับ (ดัชนี int)


237

ฉันแน่ใจว่ามีเหตุผลที่ดี แต่มีคนช่วยอธิบายได้ว่าทำไมjava.util.Setอินเทอร์เฟซขาดget(int Index)หรือget()วิธีการที่คล้ายกัน?

ดูเหมือนว่าฉากนั้นยอดเยี่ยมมากสำหรับการใส่สิ่งต่าง ๆ แต่ฉันไม่สามารถหาวิธีที่สง่างามในการรับไอเท็มชิ้นเดียวจากมัน

ถ้าฉันรู้ว่าฉันต้องการไอเท็มแรกฉันสามารถใช้set.iterator().next()แต่อย่างอื่นมันดูเหมือนว่าฉันต้องส่ง Array เพื่อดึงไอเท็มที่ดัชนีเฉพาะหรือไม่?

วิธีการที่เหมาะสมในการดึงข้อมูลจากชุดคืออะไร? (นอกเหนือจากการใช้ตัววนซ้ำ)

ฉันแน่ใจว่าความจริงที่ว่ามันถูกแยกออกจาก API หมายความว่ามีเหตุผลที่ดีที่จะไม่ทำสิ่งนี้ - ใครบางคนได้โปรดให้ความรู้แก่ฉันได้ไหม

แก้ไข: คำตอบที่ยอดเยี่ยมบางอย่างที่นี่และบางคำพูดที่ว่า "บริบทเพิ่มเติม" สถานการณ์เฉพาะคือการทดสอบ dbUnit ซึ่งฉันสามารถยืนยันได้อย่างสมเหตุสมผลว่าชุดที่ส่งคืนจากแบบสอบถามมีเพียง 1 รายการและฉันพยายามเข้าถึงรายการนั้น

อย่างไรก็ตามคำถามจะมีความถูกต้องมากขึ้นหากไม่มีสถานการณ์สมมติเนื่องจากยังคงเน้นไปที่:

ความแตกต่างระหว่างชุดและรายการคืออะไร

ขอบคุณทุกคำตอบที่น่าอัศจรรย์ด้านล่าง


1
ทำไมคุณจะได้รับองค์ประกอบจากชุดโดยดัชนี? คุณพยายามที่จะใช้ชุดเป็นอาร์เรย์เรียง?
— MSN

อินสแตนซ์เฉพาะที่นี่คือการทดสอบ dbUnit กับชุดที่ส่งคืนจากการโทรไฮเบอร์เนต ในการทดสอบของฉันมีเหตุผลที่จะถือว่า (เพราะฉันยืนยัน) ว่าวัตถุที่ส่งคืนนั้นอยู่ในลำดับที่เฉพาะเจาะจงเนื่องจาก IDataSet ของฉันฉันใช้ในการตั้งค่า มันไม่ใช่กรณีทั่วไป แต่นำไปสู่ความอยากรู้เกี่ยวกับ API ของฉัน
— Marty Pitt

1
การเพิ่มสิ่งต่าง ๆ ในลำดับที่เฉพาะเจาะจงไม่ได้หมายความว่าสิ่งนั้นจะยังคงอยู่ในลักษณะนั้นเว้นแต่คุณจะใช้การติดตั้งแบบกำหนดเอง
— Michael Myers

1
"ถ้าฉันรู้ว่าฉันต้องการรายการแรกฉันสามารถใช้ set.iterator (). next ()" - บรรทัดนี้ไม่สมเหตุสมผล คุณกำลังพูดว่า "ถ้าฉันรู้ว่าฉันต้องการไอเท็มแรกโดยคำจำกัดความของการใช้ไอเท็มแรกจากนั้นฉันก็สามารถ ... " ตั้งค่าตัวเองไม่ได้จัดลำดับดังนั้นการเข้าถึงดัชนีจึงไม่สมเหตุสมผล ตอนนี้ถ้ามี ArrayListSet นั่นจะทำให้เข้าใจได้ง่ายขึ้น (เพียงนำไปใช้กับ "รายการ" และมีความสุข) บางทีคุณอาจให้บริบทเพิ่มเติมสำหรับคำถาม
— jsight

ชุดนี้ไม่ได้เรียงลำดับ! การใช้งานบางอย่างของมันคือ แต่การใช้งานบางอย่างมีการจัดเรียงอย่างชัดเจนในวิธีการเฉพาะ
— reinierpost

คำตอบ:


176

เพราะเซตไม่มีคำสั่ง การใช้งานบางอย่างทำ (โดยเฉพาะผู้ที่ใช้งานjava.util.SortedSetอินเทอร์เฟซ) แต่นั่นไม่ใช่คุณสมบัติทั่วไปของชุด

หากคุณกำลังพยายามใช้ตั้งค่าด้วยวิธีนี้คุณควรลองใช้รายการแทน


10
@matt b: ไม่ฉันคิดว่าเขาควรจะพิจารณามัน การคิดเป็นสิ่งที่ดี ;)
— Michael Myers

10
พิจารณาแล้วทำ
— Joe Phillips

21
"พิจารณา" เป็นประโยคที่ถูกต้อง มีปัญหาที่เป็นไปได้สองข้อ (ก) เขากำลังใช้เซตเมื่อเขาควรใช้อย่างอื่นหรือ (b) เขาพยายามทำสิ่งต่าง ๆ กับเซตที่พวกเขาไม่สนับสนุน แต่เขาสามารถทำวิธีอื่นได้ มันเป็นการดีที่จะพิจารณาว่าสิ่งเหล่านี้เป็นกรณีใด
— kenj0418

6
อาจเป็นคำตอบที่ง่ายกว่าคือการใช้ชุดเรียง (ฉันถือว่าเป็นส่วนหนึ่งในการเลือกชุด) แต่ฉันมีคำถามสรรพสินค้าเนื่องจาก SortedSet ได้รับคำสั่งแล้วทำไมไม่มีวิธีรับใน api
— uncaught_exceptions

5
@HDave: ไม่ความจริงที่ว่าการใช้งานหลายโครงสร้างข้อมูลใช้คุณสมบัติร่วมกันไม่ได้ทำให้เป็นคุณสมบัติของโครงสร้างข้อมูลเอง สองในสามของการใช้งานทั่วไปของรายการ (ArrayList และ Vector) เป็นการเข้าถึงแบบสุ่ม แต่ไม่ได้ทำการเข้าถึงแบบสุ่มคุณสมบัติของรายการ
— Michael Myers

74

ที่จริงแล้วนี่เป็นคำถามที่เกิดขึ้นซ้ำเมื่อเขียนแอปพลิเคชัน JavaEE ที่ใช้การทำแผนที่วัตถุเชิงสัมพันธ์ (ตัวอย่างเช่นไฮเบอร์เนต); และจากทุกคนที่ตอบกลับมาที่นี่ Andreas Petersson เป็นคนเดียวที่เข้าใจปัญหาจริงและเสนอคำตอบที่ถูกต้อง: Java ไม่พบ UniqueList! (หรือคุณสามารถเรียกมันว่า OrderedSet หรือ IndexedSet)

Maxwing กล่าวถึงกรณีการใช้งานนี้ (ซึ่งคุณต้องการสั่งซื้อและข้อมูลที่ไม่ซ้ำกัน) และเขาแนะนำ SortedSet แต่นี่ไม่ใช่สิ่งที่ Marty Pitt ต้องการจริงๆ

"IndexedSet" นี้ไม่เหมือนกับ SortedSet - ใน SortedSet อิลิเมนต์จะเรียงลำดับโดยใช้ Comparator (หรือใช้การเรียงลำดับ "แบบธรรมชาติ")

แต่มันอยู่ใกล้กับ LinkedHashSet (ซึ่งคนอื่นแนะนำด้วย) หรือมากกว่านั้นไปที่ "ArrayListSet" (ยังไม่ใช้งาน) เพราะมันรับประกันว่าองค์ประกอบจะถูกส่งกลับในลำดับเดียวกันกับที่พวกมันถูกแทรกเข้าไป

แต่ LinkedHashSet เป็นการใช้งานไม่ใช่ส่วนต่อประสาน! สิ่งที่จำเป็นคืออินเทอร์เฟซ IndexedSet (หรือ ListSet หรือ OrderedSet หรือ UniqueList) สิ่งนี้จะช่วยให้โปรแกรมเมอร์ระบุว่าเขาต้องการคอลเลกชันขององค์ประกอบที่มีคำสั่งเฉพาะและไม่มีการทำซ้ำจากนั้นสร้างอินสแตนซ์กับการใช้งานใด ๆ (ตัวอย่างเช่นการใช้งานที่ให้ไว้โดย Hibernate)

เนื่องจาก JDK เป็นโอเพ่นซอร์สบางทีในที่สุดอินเทอร์เฟซนี้จะรวมอยู่ใน Java 7 ...


3
คำตอบที่ดีที่สุดเท่าที่จะทำได้ แต่เราจะทำอย่างไรในระหว่างนี้?
— HDave

แน่นอนมันเป็น ฉันใช้รายการเป็นจำนวนมากและ onetomany ORM ในโหมดไฮเบอร์เนตก่อน ฉันพบปัญหา (หรือข้อบกพร่อง) เมื่อคิวรีการเข้าร่วมด้านซ้ายเกี่ยวข้องกับเอนทิตีที่เกี่ยวข้องมากกว่า 3 รายการข้อยกเว้นถูกส่งออกไป ดูที่นี่สำหรับรายละเอียดเพิ่มเติม ( jroller.com/eyallupu/entry/… ) หากต้องการแก้ไขปัญหานี้ให้ใช้การตั้งค่าเป็นชุดเก็บรวบรวมการทำแผนที่ ORM เป็นสิ่งจำเป็น แต่บอกตามตรงว่าชุดไม่สะดวกสำหรับการเข้าถึงในการเขียนโปรแกรมและเมื่อคุณต้องการสั่งซื้อชุด สิ่งที่เราต้องการจริงๆคือ "indexedset" เหมือนที่ Sorin Postelnicu พูดไว้เรียงลำดับและไม่ซ้ำกัน
— horaceman

2
Apache Commons Collections มีListOrderedSetสิ่งที่ OP ต้องการเมื่อ 7 ปีที่แล้ว (และฉันต้องการวันนี้)
— Paul

@ พอล: นั่นเป็นสิ่งที่ดูดีจริงๆ น่าเสียดายที่มันยังคงมีข้อเสียอยู่ 3 ข้อ: 1) เป็นคลาสไม่ใช่อินเทอร์เฟซ 2) มันไม่ได้อยู่ใน JDK 3) มันไม่ใช่สิ่งที่แบบสอบถามไฮเบอร์เนตจะกลับมา
— โซริน Postelnicu

ใช่ แต่นอกเหนือจากข้อเสียที่สำคัญ 3 ข้อนั้นมันสมบูรณ์แบบ! :) ในการหวนกลับฉันควรจะได้โพสต์ความคิดเห็นของฉันกับคำถามและคำตอบของคุณไม่ได้ - ฉันเครียดออกและละเว้นWhat is needed is an IndexedSet (or ListSet, or OrderedSet, or UniqueList)... ...interfaceขอโทษด้วยกับเรื่องนั้น!
— พอล

29

เพียงแค่เพิ่มจุดหนึ่งที่ไม่ได้กล่าวถึงในคำตอบ mmyers'

ถ้าฉันรู้ว่าฉันต้องการไอเท็มแรกฉันสามารถใช้ set.iterator (). next () แต่ไม่เช่นนั้นฉันต้องส่ง Array เพื่อดึงไอเท็มที่ดัชนีเฉพาะหรือไม่

วิธีการที่เหมาะสมในการดึงข้อมูลจากชุดคืออะไร? (นอกเหนือจากการใช้ตัววนซ้ำ)

คุณควรทำความคุ้นเคยกับSortedSetอินเทอร์เฟซ (ซึ่งมีการใช้งานทั่วไปTreeSet)

SortedSet เป็นชุด (องค์ประกอบคือจะไม่ซ้ำกัน) ที่ถูกเก็บไว้ได้รับคำสั่งจากการสั่งซื้อตามธรรมชาติComparatorของธาตุหรือใช้บางส่วน คุณสามารถเข้าถึงรายการแรกและสุดท้ายโดยใช้first()และlast()วิธีการ A SortedSetมีประโยชน์ทุกครั้งในบางครั้งเมื่อคุณต้องการเก็บคอลเล็กชันของคุณทั้งสองแบบไม่ซ้ำกันและสั่งซื้อในบางวิธี

แก้ไข : ถ้าคุณต้องการชุดที่มีองค์ประกอบที่ถูกเก็บไว้ในการแทรกการสั่งซื้อ (เหมือนรายการ) LinkedHashSetจะดูที่


ฉันชอบ LinkedHashSet ด้วยตัวเอง แต่ใช่มันเป็นสิ่งที่ดีที่จะพูดถึง +1
— Michael Myers

ขอบคุณฉัน tweaked คำตอบเล็กน้อย (ดูเหมือนว่าฉันมีบางแง่มุมของ TreeSet สับสนกับผู้ LinkedHashSet.)
— Jonik

25

ประเภทนี้นำไปสู่คำถามเมื่อคุณควรใช้ชุดและเมื่อคุณควรใช้รายการ โดยปกติแล้วคำแนะนำ:

  1. หากคุณต้องการข้อมูลที่สั่งซื้อให้ใช้รายการ
  2. หากคุณต้องการข้อมูลที่ไม่ซ้ำให้ใช้ชุด
  3. หากคุณต้องการทั้งสองอย่างให้ใช้: SortedSet (สำหรับข้อมูลที่เรียงลำดับโดยเครื่องมือเปรียบเทียบ) หรือ OrderedSet / UniqueList (สำหรับข้อมูลที่เรียงลำดับโดยการแทรก) น่าเสียดายที่ Java API ยังไม่มี OrderedSet / UniqueList

กรณีที่สี่ที่ปรากฏบ่อยคือคุณไม่ต้องการ ในกรณีนี้คุณจะเห็นโปรแกรมเมอร์บางคนไปกับรายการและบางส่วนมีชุด โดยส่วนตัวแล้วฉันคิดว่ามันอันตรายมากที่เห็นชุดเป็นรายการโดยไม่ต้องสั่ง - เพราะมันเป็นสัตว์ร้ายอื่นทั้งหมด หากคุณไม่ต้องการสิ่งต่าง ๆ เช่นการตั้งค่าความเป็นเอกลักษณ์หรือความเท่าเทียมกันให้กำหนดรายการโปรด


2
หากคุณไม่เจาะจงให้ยอมรับ Collection <T> หรือ Iterable <T> และเริ่มต้นเป็นรายการ
— Andreas Petersson

นี่จะเป็นกระเป๋าหรือมัลติเซ็ต แต่ Java ไม่รองรับสิ่งเหล่านั้น พวกเขาบอกว่าคุณควรใช้ Collection <T> โดยตรง
— หอยทากเครื่องกล

4. คุณต้องการข้อมูลที่ไม่ซ้ำและไม่สนใจเกี่ยวกับการสั่งซื้อ คุณไม่สามารถใช้ชุด รายการกระเป๋าหรือ Multiset จะใช้งานได้
— Andrew Gallasch

17

ฉันไม่แน่ใจว่ามีใครสะกดมันออกมาอย่างแน่นอน แต่คุณต้องเข้าใจสิ่งต่อไปนี้:

ไม่มีองค์ประกอบ "แรก" ในชุด

เพราะอย่างที่คนอื่นพูดชุดไม่มีคำสั่ง ชุดเป็นแนวคิดทางคณิตศาสตร์ที่ไม่รวมถึงการสั่งซื้อโดยเฉพาะ

แน่นอนคอมพิวเตอร์ของคุณไม่สามารถเก็บรายการสิ่งที่ไม่ได้สั่งไว้ในหน่วยความจำได้ ต้องมีการสั่งซื้อ ภายในนั้นเป็นอาร์เรย์หรือรายการที่เชื่อมโยงหรือบางสิ่งบางอย่าง แต่คุณไม่รู้จริงๆว่ามันคืออะไรและมันไม่มีองค์ประกอบแรกเลย องค์ประกอบที่ออกมาเป็น "ครั้งแรก" ออกมาโดยบังเอิญและอาจไม่เป็นครั้งแรกในครั้งต่อไป แม้ว่าคุณจะทำตามขั้นตอนในการ "รับประกัน" องค์ประกอบแรกโดยเฉพาะมันยังคงออกมาโดยบังเอิญเพราะคุณเพิ่งจะทำให้มันถูกต้องสำหรับการใช้งานชุดหนึ่งโดยเฉพาะ การใช้งานที่แตกต่างกันอาจไม่ทำงานอย่างที่คุณทำ และในความเป็นจริงคุณอาจไม่ทราบว่าการใช้งานที่คุณใช้นั้นเป็นอย่างไรอย่างที่คุณคิด

ผู้คนวิ่งเข้ามาหาสิ่งนี้ทั้งหมด เวลา. กับระบบ RDBMS และไม่เข้าใจ แบบสอบถาม RDBMS ส่งคืนชุดของระเบียน นี่เป็นชุดประเภทเดียวกันจากคณิตศาสตร์: ชุดของรายการที่ไม่เรียงลำดับเฉพาะในกรณีนี้รายการนั้นเป็นบันทึก ผลลัพธ์แบบสอบถาม RDBMS ไม่มีการรับประกันการสั่งซื้อเลยเว้นแต่ว่าคุณจะใช้คำสั่ง ORDER BY แต่ทุกครั้งที่ผู้คนคิดว่ามันทำแล้วเดินทางด้วยตัวเองในบางวันเมื่อรูปร่างของข้อมูลหรือรหัสเปลี่ยนแปลงเล็กน้อยและทำให้เครื่องมือเพิ่มประสิทธิภาพแบบสอบถามทำงาน วิธีที่แตกต่างและทันใดนั้นผลลัพธ์ก็ไม่ออกมาตามลำดับที่พวกเขาคาดหวัง โดยทั่วไปเป็นคนที่ไม่สนใจในคลาสฐานข้อมูล (หรือเมื่ออ่านเอกสารหรือแบบฝึกหัด) เมื่อมีการอธิบายให้พวกเขาล่วงหน้าผลแบบสอบถามนั้นไม่มีการรับประกันการสั่งซื้อ


Heh และแน่นอนว่าการสั่งซื้อมักจะเปลี่ยนไปทันทีหลังจากที่รหัสเข้าสู่การผลิตเมื่อมันช้าเกินไปดังนั้นพวกเขาจึงเพิ่มดัชนีเพื่อเพิ่มความเร็วในการสืบค้น ตอนนี้โค้ดทำงานเร็ว แต่ให้คำตอบที่ผิด และไม่มีใครสังเกตเห็นสามหรือสี่วัน ... ถ้าคุณโชคดี หากคุณไม่ได้โชคดีไม่มีใครประกาศสำหรับเดือน ...
— TMN

ฉันไม่คิดว่าเขาจะพลาดมัน เขาไม่ต้องการองค์ประกอบแรกจากชุดเขาต้องการองค์ประกอบที่กำหนดเองจากชุด คุณสามารถให้เขาเป็นองค์ประกอบพลตั้งแต่เป็นSet Iterable
— Elazar Leibovich

คุณกำลังพูดถึงรับ (ดัชนี) โดยดัชนี สิ่งที่เกี่ยวกับการรับ (Object) โดยความเท่าเทียมกัน?
— Kumar Manish

10

โครงสร้างข้อมูลบางอย่างหายไปจากคอลเลกชัน java มาตรฐาน

กระเป๋า (เช่นชุด แต่สามารถมีองค์ประกอบได้หลายครั้ง)

UniqueList (รายการที่สั่งซื้อสามารถมีแต่ละองค์ประกอบได้เพียงครั้งเดียว)

ดูเหมือนว่าคุณจะต้องมีผู้ที่ไม่ซ้ำกันในกรณีนี้

หากคุณต้องการโครงสร้างข้อมูลที่ยืดหยุ่นคุณอาจสนใจGoogle Collections


1
Guva มี "UniqueList" หรือไม่
— Mike Rylander

ไม่ แต่คุณสามารถมี java.util.LinkedHashSet ที่มีคุณสมบัติคล้ายกัน
— Andreas Petersson

7

นั่นเป็นความจริงองค์ประกอบใน Set ไม่ได้ถูกจัดเรียงตามคำจำกัดความของ Set Collection ดังนั้นดัชนีจึงไม่สามารถเข้าถึงได้

แต่ทำไมเราไม่มีเมธอด get (object) ไม่ใช่โดยการจัดทำดัชนีเป็นพารามิเตอร์ แต่วัตถุที่เท่ากับที่เรากำลังค้นหาอยู่ ด้วยวิธีนี้เราสามารถเข้าถึงข้อมูลขององค์ประกอบภายในชุดเพียงแค่รู้ว่าคุณลักษณะของมันถูกใช้โดยวิธีที่เท่ากัน


7

หากคุณจะทำการเข้าถึงแบบสุ่มจำนวนมากตามดัชนีในชุดคุณสามารถรับมุมมองอาร์เรย์ขององค์ประกอบ:

Object[] arrayView = mySet.toArray();
//do whatever you need with arrayView[i]

มีสองข้อเสียเปรียบหลักแม้ว่า:

  1. ไม่มีหน่วยความจำที่มีประสิทธิภาพเนื่องจากต้องสร้างอาร์เรย์สำหรับทั้งชุด
  2. หากชุดถูกแก้ไขมุมมองจะล้าสมัย

5

นั่นเป็นเพราะ Set รับประกันความเป็นเอกลักษณ์เท่านั้น แต่ไม่ได้พูดถึงการเข้าถึงหรือรูปแบบการใช้งานที่เหมาะสมที่สุด เช่นชุดสามารถเป็นรายการหรือแผนที่ซึ่งแต่ละชุดมีคุณสมบัติการดึงข้อมูลที่แตกต่างกันมาก


5

เหตุผลเดียวที่ฉันนึกถึงการใช้ดัชนีตัวเลขในชุดนั้นสำหรับการทำซ้ำ สำหรับสิ่งที่ใช้

for(A a : set) { 
   visit(a); 
}

ไม่จริงสิ่งที่เกี่ยวกับการเข้าถึงองค์ประกอบแบบสุ่ม?
— Jeremy Salwen

ฮ่า. จุดที่ดี :) แต่ที่จะมีแนวโน้มสูงที่จะใช้ผิดฉันแน่ใจ
— Hugo

3

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

ฉันต้องการการเข้าถึงผ่านดัชนีเพื่อแสดงและคุณลักษณะชุดมีประโยชน์เพื่อกำจัดรายการที่ซ้ำกันได้อย่างมีประสิทธิภาพ

การหาคอลเลกชันที่ไม่เหมาะสมใน java.util หรือ Google คอลเลคชันฉันพบว่าใช้งานได้ง่าย แนวคิดพื้นฐานคือการห่อ SortedSet และสร้างรายการเมื่อจำเป็นต้องใช้การเข้าถึงผ่านดัชนี (และลืมรายการเมื่อมีการเปลี่ยนแปลง SortedSet) แน่นอนว่าจะทำงานได้อย่างมีประสิทธิภาพเมื่อเปลี่ยน SortedSet ที่ห่อไว้และการเข้าถึงรายการจะถูกแยกออกจากอายุการใช้งานของคอลเลกชัน มิฉะนั้นมันจะทำงานเหมือนรายการที่เรียงลำดับบ่อยครั้งเช่นช้าเกินไป

ด้วยเด็กจำนวนมากประสิทธิภาพที่ได้รับการปรับปรุงนี้มีมากกว่ารายการที่ฉันจัดเรียงผ่าน Collections.sort


2

โปรดทราบเพียง 2 โครงสร้างข้อมูลพื้นฐานสามารถเข้าถึงได้ผ่านดัชนี

  • โครงสร้างข้อมูลArrayสามารถเข้าถึงได้ผ่านดัชนีที่มีO(1)ความซับซ้อนของเวลาในget(int index)การดำเนินการ
  • โครงสร้างข้อมูลLinkedListสามารถเข้าถึงได้ผ่านดัชนี แต่มีO(n)ความซับซ้อนของเวลาในget(int index)การดำเนินการ

ใน Java นั้นArrayListถูกใช้งานโดยใช้โครงสร้างข้อมูลArray

ในขณะที่ชุดโครงสร้างข้อมูลสามารถจะดำเนินการผ่านทางHashTable / HashMapหรือBalancedTreeโครงสร้างข้อมูลได้อย่างรวดเร็วการตรวจสอบว่าเป็นองค์ประกอบที่มีอยู่และเพิ่มไม่ใช่ที่มีอยู่องค์ประกอบมักจะดำเนินการอย่างดีชุดสามารถบรรลุO(1)ความซับซ้อนเวลาcontainsการดำเนินงาน ใน Java HashSetเป็นการใช้งานที่พบบ่อยที่สุดของSetมันถูกนำไปใช้โดยการเรียกHashMapAPI และHashMapนำมาใช้โดยแยกการโยงกับรายการเชื่อมโยง (การรวมกันของArrayและLinkedList )

เนื่องจากSetสามารถใช้งานผ่านโครงสร้างข้อมูลที่แตกต่างกันจึงไม่มีget(int index)วิธีการใดๆ


ต้นไม้นิ้ว (ดูData.Sequence.lookupฟังก์ชั่นของ Haskell ) ยังอนุญาตให้เข้าถึงผ่านดัชนี ( O(1)ใกล้สิ้นสุดO(log n)ใกล้กลาง, แม่นยำมากขึ้นO(min(log(k), log(n-k)))), ต้นไม้ไบนารีก็ทำเช่นกัน (ดูData.Set.lookupIndexฟังก์ชั่นของ Haskell ) ดังนั้นการยืนยันเริ่มต้นของคุณว่า "โปรดทราบเพียง 2 โครงสร้างข้อมูลพื้นฐานที่สามารถเข้าถึงได้ผ่านดัชนี" ไม่ถูกต้อง
— เซมิโคลอน

1

เหตุผลที่อินเทอร์เฟซการตั้งค่าไม่ได้รับการเรียกชนิดดัชนีหรือแม้แต่บางสิ่งพื้นฐานมากขึ้นเช่นแรก () หรือสุดท้าย () เพราะมันเป็นการดำเนินการที่ไม่ชัดเจนและเป็นการดำเนินการที่อาจเป็นอันตราย หากวิธีการส่งกลับชุดและคุณโทรพูดวิธีแรก () ในสิ่งที่เป็นผลที่คาดหวังเนื่องจากชุดทั่วไปที่ไม่รับประกันในการสั่งซื้อ? วัตถุที่เป็นผลลัพธ์อาจแตกต่างกันมากระหว่างการเรียกใช้แต่ละวิธีหรืออาจและไม่ทำให้คุณรู้สึกปลอดภัยจนกว่าห้องสมุดที่คุณใช้การเปลี่ยนแปลงจะมีการเปลี่ยนแปลงการใช้งานภายใต้และตอนนี้คุณพบว่ารหัสทั้งหมดของคุณแบ่งสำหรับ ไม่มีเหตุผลพิเศษ

คำแนะนำเกี่ยวกับวิธีแก้ไขปัญหาที่แสดงไว้ที่นี่เป็นสิ่งที่ดี หากคุณต้องการเข้าถึงดัชนีให้ใช้รายการ ระมัดระวังการใช้ตัววนซ้ำหรือ toArray กับชุดทั่วไปเพราะ a) ไม่มีการรับประกันในการสั่งซื้อและ b) ไม่มีการรับประกันว่าการสั่งซื้อจะไม่เปลี่ยนแปลงด้วยการร้องขอต่อมาหรือการใช้งานพื้นฐานที่แตกต่างกัน หากคุณต้องการบางสิ่งบางอย่างระหว่าง SortedSet หรือ LinkedHashSet เป็นสิ่งที่คุณต้องการ

// ฉันหวังว่าส่วนต่อประสาน Set จะมีองค์ประกอบแบบสุ่ม


1

java.util.Setคือชุดของรายการที่ไม่ได้สั่งซื้อ มันไม่สมเหตุสมผลหาก Set มีการรับ (ดัชนี int) เนื่องจาก Set ไม่มีดัชนีและคุณสามารถเดาค่าได้

หากคุณต้องการสิ่งนี้จริงๆให้โค้ดวิธีเพื่อรับองค์ประกอบแบบสุ่มจาก Set


0

คุณทำได้ new ArrayList<T>(set).get(index)


ส่งคืนรายการชุดและรับ (ดัชนี) ส่งคืนชุด แต่ฉันใช้: new ArrayList<T>(t).get(0) ฉันคิดว่ามีความขัดแย้งที่ถูกต้องกับความคิดของการได้รับองค์ประกอบเฉพาะจากชุดโดยดัชนี แต่มันจะดีถ้า Set มีฟังก์ชั่นสมาชิกเท่านั้น () ที่สำหรับชุดขนาด 1 ให้เข้าถึงองค์ประกอบเดียวในชุดได้ง่าย สิ่งนี้จะช่วยประหยัดค่าใช้จ่ายดังกล่าวnew ArrayListหรือfor (Foo foo : foos) { return foo; }
— Doug Moscrop

0

หากคุณไม่ทราบชุดที่จะเรียงลำดับจากนั้นคุณอาจจะสนใจที่จะดูที่การจัดทำดัชนีต้นไม้แผนที่โครงการ

TreeSet / TreeMap ที่ได้รับการปรับปรุงให้การเข้าถึงองค์ประกอบโดยใช้ดัชนีหรือรับดัชนีขององค์ประกอบ และการนำไปใช้นั้นขึ้นอยู่กับการอัพเดตน้ำหนักโหนดในทรี RB ดังนั้นไม่มีการทำซ้ำหรือสำรองข้อมูลตามรายการที่นี่


0

Set เป็นอินเทอร์เฟซและบางส่วนของคลาสการใช้งานของมันคือ HashSet, TreeSet และ LinkedHashSet มันใช้ HashMap ภายใต้ประทุนเพื่อเก็บค่า เนื่องจาก HashMap ไม่รักษาคำสั่งซื้อจึงไม่สามารถรับค่าตามดัชนี

ตอนนี้คุณต้องคิดว่า Set ใช้ HashMap อย่างไรเนื่องจาก HashMap เก็บคีย์คู่ค่าไว้ แต่ Set ไม่ คำถามที่ถูกต้อง เมื่อคุณเพิ่มองค์ประกอบในชุดภายในก็จะรักษา HashMap ที่สำคัญคือองค์ประกอบที่คุณต้องการที่จะเข้าสู่การตั้งค่าและค่าเป็นค่าคงที่จำลอง ด้านล่างคือการเพิ่มฟังก์ชั่นการใช้งานภายใน ดังนั้นคีย์ทั้งหมดใน HashMap จะมีค่าคงที่เหมือนกัน

// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

Setการใช้งานทั้งหมดของใช้HashMapภายใต้ประทุนเพื่อเก็บค่าคุณสามารถยืนยันการเรียกร้องที่TreeSet?
— greybeard

1
the keys in the HashMap will have the same constant value คีย์ในที่HashMapจะแมปไปหนึ่งเดียวกันไม่เปลี่ยนรูปObject
— greybeard


-3

ในการรับองค์ประกอบในชุดฉันใช้เพื่อติดตามองค์ประกอบ:

public T getElement(Set<T> set, T element) {
T result = null;
if (set instanceof TreeSet<?>) {
    T floor = ((TreeSet<T>) set).floor(element);
    if (floor != null && floor.equals(element))
    result = floor;
} else {
    boolean found = false;
    for (Iterator<T> it = set.iterator(); !found && it.hasNext();) {
    if (true) {
        T current = it.next();
        if (current.equals(element)) {
        result = current;
        found = true;
        }
    }
    }
}
return result;
}

ฟังก์ชั่นไม่ใช่คำถามที่ถาม เราต้องการดัชนีไม่ใช่ค่า ฟังก์ชันของคุณกำลังทำอะไรอยู่ ดูเหมือนว่ามันแค่คืนองค์ประกอบถ้ามันเท่ากับองค์ประกอบภายใน สิ่งนี้ทำอะไรที่มี () ไม่ได้?
— Janus Troelsen

ที่Tกำหนดไว้ที่ไหน ทำไมif (true)?
— ควอนตัม
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.