ทำไม 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.