Hashset กับ Treeset


496

ฉันชอบต้นไม้ที่ดีO(n*log(n))และเป็นระเบียบเรียบร้อยของพวกเขา TreeSetอย่างไรก็ตามซอฟต์แวร์วิศวกรทุกคนที่ฉันเคยรู้จักได้ถามฉันอย่างชัดเจนว่าทำไมฉันจะใช้ จากแบ็คกราวน์ CS ฉันไม่คิดว่ามันจะสำคัญกับทุกอย่างที่คุณใช้และฉันก็ไม่สนใจที่จะยุ่งกับฟังก์ชั่นแฮชและที่เก็บข้อมูล (ในกรณีของJava)

ในกรณีใดบ้างที่ฉันควรใช้HashSeta TreeSet?

คำตอบ:


860

HashSet เร็วกว่า TreeSet มาก (เวลาคงที่และเวลาล็อกสำหรับการดำเนินการส่วนใหญ่เช่นเพิ่มลบและมี) แต่ไม่มีการรับประกันการสั่งซื้อเช่น TreeSet

HashSet

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

TreeSet

  • รับประกันบันทึกเวลา (n) ค่าใช้จ่ายเวลาสำหรับการดำเนินงานขั้นพื้นฐาน (เพิ่มลบและมี)
  • รับประกันว่าองค์ประกอบของชุดจะถูกจัดเรียง (น้อยไปหามากตามธรรมชาติหรือสิ่งที่คุณระบุผ่านตัวสร้าง) (ดำเนินการSortedSet)
  • ไม่มีพารามิเตอร์การปรับแต่งสำหรับประสิทธิภาพการทำซ้ำ
  • ข้อเสนอวิธีการที่มีประโยชน์น้อยที่จะจัดการกับชุดคำสั่งให้เหมือนfirst(), last(), headSet()และtailSet()ฯลฯ

จุดสำคัญ:

  • ทั้งสองรับประกันการเก็บองค์ประกอบที่ไม่ซ้ำกัน
  • โดยทั่วไปจะเร็วกว่าในการเพิ่มองค์ประกอบลงใน HashSet แล้วแปลงคอลเลกชันเป็น TreeSet เพื่อการสำรวจเส้นทางที่ไม่มีการเรียงซ้ำ
  • การปรับใช้เหล่านี้ไม่มีการซิงโครไนซ์ นั่นคือถ้าหลายเธรดเข้าถึงชุดพร้อมกันและอย่างน้อยหนึ่งเธรดที่แก้ไขชุดนั้นต้องถูกซิงโครไนซ์ภายนอก
  • LinkedHashSetอยู่ในระดับกลางระหว่างHashSetและTreeSetและนำมาใช้เป็นตารางแฮชที่มีรายการที่เชื่อมโยงการทำงานผ่านมัน แต่ก็มีการทำซ้ำแทรกสั่งซื้อที่ไม่ได้เช่นเดียวกับการเรียงลำดับ traversal ค้ำประกันโดย TreeSet

ทางเลือกในการใช้งานขึ้นอยู่กับความต้องการของคุณ แต่ฉันรู้สึกว่าแม้ว่าคุณต้องการคอลเลกชันที่สั่งซื้อแล้วคุณก็ควรที่จะชอบ HashSet เพื่อสร้างชุดแล้วแปลงเป็นชุด

  • เช่น SortedSet<String> s = new TreeSet<String>(hashSet);

38
เป็นเพียงฉันเท่านั้นที่พบว่าการยืนยัน "HashSet เร็วกว่า TreeSet มาก (เวลาคงที่และเวลาเข้าสู่ระบบ ... )" ผิดอย่างชัดเจนใช่ไหม ครั้งแรกว่านี่เป็นเรื่องเกี่ยวกับความซับซ้อนของเวลาไม่ใช่เวลาที่แน่นอนและ O (1) อาจช้ากว่า O (f (N)) มากเกินไป ที่สองที่ O (logN) คือ "เกือบ" O (1) ฉันจะไม่แปลกใจถ้าในกรณีทั่วไปที่ TreeSet มีประสิทธิภาพสูงกว่า HashSet
lvella

22
ฉันแค่ต้องการแสดงความคิดเห็นที่สองของ Ivella ความซับซ้อนของเวลานั้นไม่เหมือนกับเวลาทำงานและ O (1) นั้นไม่ได้ดีไปกว่า O (2 ^ n) เสมอไป ตัวอย่างที่ผิดปกติแสดงให้เห็นถึงจุด: พิจารณาชุดแฮชโดยใช้อัลกอริทึมแฮชที่ใช้คำสั่งเครื่อง 1 ล้านล้านคำสั่งเพื่อดำเนินการ (O (1)) เทียบกับการใช้งานทั่วไปของการเรียงลำดับฟอง (O (N ^ 2) เฉลี่ย / แย่ที่สุด) สำหรับ 10 องค์ประกอบ . การเรียงลำดับฟองจะชนะทุกครั้ง ประเด็นก็คือการเรียนการสอนขั้นตอนวิธีการทุกคนที่จะคิดเกี่ยวกับการประมาณโดยใช้เวลาซับซ้อน แต่ในโลกแห่งความเป็นจริงปัจจัยอย่างต่อเนื่องก็ตามบ่อย
Peter Oehlert

17
บางทีมันอาจเป็นแค่ฉัน แต่ไม่ใช่คำแนะนำในการเพิ่มทุกอย่างลงในแฮชเซ็ตก่อนจากนั้นซ่อนไว้ในชุดต้นไม้ที่น่ากลัวใช่ไหม 1) การแทรกในชุดแฮชเซ็ตนั้นรวดเร็วถ้าคุณรู้ขนาดของชุดข้อมูลของคุณล่วงหน้ามิฉะนั้นคุณจะต้องจ่าย O (n) การแฮชอีกครั้งอาจมีหลายครั้ง และ 2) คุณจ่ายสำหรับการแทรก TreeSet ต่อไปเมื่อทำการแปลงชุด (ด้วยการล้างแค้นเพราะการทำซ้ำผ่านแฮชเซ็ตนั้นไม่มีประสิทธิภาพมากนัก)
TinkerTank

5
คำแนะนำนี้ขึ้นอยู่กับความจริงที่ว่าสำหรับชุดคุณต้องตรวจสอบเพื่อดูว่ารายการที่ซ้ำกันก่อนที่จะเพิ่ม; ดังนั้นคุณจะประหยัดเวลาในการกำจัดข้อมูลที่ซ้ำกันหากคุณใช้ hashset บนชุดต้นไม้ อย่างไรก็ตามการพิจารณาราคาที่จะจ่ายสำหรับการสร้างชุดที่สองสำหรับผู้ที่ไม่ได้ซ้ำซ้อนเปอร์เซ็นต์ของการทำซ้ำควรจะยอดเยี่ยมจริง ๆ เพื่อเอาชนะราคานี้และทำให้ประหยัดเวลา และแน่นอนว่านี่เป็นชุดขนาดกลางและขนาดใหญ่เพราะสำหรับชุดเล็กชุดต้นไม้อาจเร็วกว่าชุดแฮช
SylvainL

5
@PeterOehlert: โปรดระบุมาตรฐานสำหรับสิ่งนั้น ฉันเข้าใจประเด็นของคุณ แต่ความแตกต่างระหว่างทั้งสองชุดนั้นแทบไม่มีความสำคัญกับคอลเล็กชั่นขนาดเล็ก และทันทีที่ชุดข้อมูลเติบโตถึงจุดที่การใช้งานมีความสำคัญ log (n) กำลังกลายเป็นปัญหา โดยทั่วไปคือฟังก์ชั่นแฮช (แม้กระทั่งที่ซับซ้อน) ขนาดของการสั่งซื้อที่เร็วกว่าการพลาดแคชหลายครั้ง (ซึ่งคุณมีบนต้นไม้ขนาดใหญ่สำหรับเกือบทุกระดับที่เข้าถึงได้) เพื่อค้นหา / เข้าถึง / เพิ่ม / แก้ไขใบไม้ อย่างน้อยนั่นคือประสบการณ์ของฉันกับสองชุดนี้ใน Java
Bouncner

38

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

นี่คือตรงกันข้ามกับ a HashSetซึ่งกระจายรายการทั่วหน่วยความจำไม่ว่าคีย์ของพวกเขาคืออะไร

เมื่อค่าเวลาแฝงในการอ่านจากฮาร์ดไดรฟ์เป็นพัน ๆ ครั้งค่าใช้จ่ายในการอ่านจากแคชหรือ RAM และเมื่อข้อมูลถูกเข้าถึงด้วยโลคอลจริง ๆ ก็เป็นTreeSetตัวเลือกที่ดีกว่ามาก


3
คุณสามารถแสดงให้เห็นว่าถ้ารายการที่สองในบริเวณใกล้เคียงเพื่อเป็น TreeSet วางไว้ใกล้ ๆ กันในโครงสร้างข้อมูลและด้วยเหตุนี้ในหน่วยความจำ ?
David Soroko

6
ค่อนข้างไม่เกี่ยวข้องกับ Java องค์ประกอบของชุดนั้นเป็นวัตถุแล้วชี้ไปที่อื่นดังนั้นคุณจะไม่บันทึกอะไรมากมาย
Andrew Gallasch

นอกจากความคิดเห็นอื่น ๆ ที่เกี่ยวกับการขาดสถานที่ใน Java โดยทั่วไปแล้วการใช้TreeSet/ TreeMapไม่ได้รับการปรับให้เหมาะสมของ OpenJDK แม้ว่ามันจะเป็นไปได้ที่จะใช้ b-tree ลำดับที่ 4 เพื่อเป็นตัวแทนของต้นไม้สีแดงดำและทำให้การปรับปรุงท้องถิ่นและประสิทธิภาพแคชไม่ได้เป็นวิธีการใช้งาน แต่โหนดแต่ละร้านค้าตัวชี้ไปที่สำคัญของตัวเองค่าของตัวเองพ่อแม่ของตนและด้านซ้ายและด้านขวาของเด็กต่อมน้ำมันเห็นได้ชัดในรหัสที่มา JDK 8 สำหรับ TreeMap.Entry
kbolino

25

HashSetคือ O (1) ในการเข้าถึงองค์ประกอบดังนั้นมันจึงสำคัญ แต่การรักษาลำดับของวัตถุในชุดเป็นไปไม่ได้

TreeSetมีประโยชน์หากการรักษาคำสั่งซื้อ (ในแง่ของคุณค่าและไม่ใช่ลำดับการแทรก) มีความสำคัญต่อคุณ แต่ดังที่คุณได้บันทึกไว้คุณกำลังทำการซื้อขายเพื่อให้เข้าถึงองค์ประกอบได้ช้าลง: O (บันทึก n) สำหรับการดำเนินการขั้นพื้นฐาน

จากjavadocs สำหรับTreeSet :

การดำเนินการนี้จะให้ค่าใช้จ่ายในการเข้าสู่ระบบ (n) เวลารับประกันสำหรับการดำเนินงานพื้นฐาน ( add, removeและcontains)


22

1.HashSet อนุญาตให้วัตถุเป็นโมฆะ

2.TreeSet จะไม่อนุญาตให้มีวัตถุว่างเปล่า ถ้าคุณพยายามที่จะเพิ่มค่า Null มันจะโยน NullPointerException

3.HashSet เร็วกว่า TreeSet มาก

เช่น

 TreeSet<String> ts = new TreeSet<String>();
 ts.add(null); // throws NullPointerException

 HashSet<String> hs = new HashSet<String>();
 hs.add(null); // runs fine

3
ts.add (null) มันจะทำงานได้ดีในกรณีของ TreeSet หากมีการเพิ่มค่า null เป็น Object แรกใน TreeSet และวัตถุใด ๆ ที่เพิ่มเข้าไปหลังจากนั้นจะให้ NullPointerException ในเมธอด comparTo ของ Comparator
Shoaib Chikate

2
คุณไม่ควรเพิ่มnullชุดของคุณลงไปด้วย
ปุย

TreeSet<String> badassTreeSet = new TreeSet<String>(new Comparator<String>() { public int compare(String string1, String string2) { if (string1 == null) { return (string2 == null) ? 0 : -1; } else if (string2 == null) { return 1; } else { return string1.compareTo(string2); } } }); badassTreeSet.add("tree"); badassTreeSet.add("asdf"); badassTreeSet.add(null); badassTreeSet.add(null); badassTreeSet.add("set"); badassTreeSet.add("tree"); System.out.println(badassTreeSet);
DávidHorváth

21

การอ้างอิงจากคำตอบที่น่ารักบน Maps โดย @shevchyk นี่คือสิ่งที่ฉันต้องทำ:

╔══════════════╦═════════════════════╦═══════════════════╦═════════════════════╗
   Property          HashSet             TreeSet           LinkedHashSet   
╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
                no guarantee order  sorted according                       
   Order       will remain constant to the natural        insertion-order  
                    over time          ordering                            
╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
 Add/remove           O(1)              O(log(n))             O(1)         
╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
                                      NavigableSet                         
  Interfaces           Set                Set                  Set         
                                       SortedSet                           
╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
                                       not allowed                         
  Null values        allowed        1st element only        allowed        
                                        in Java 7                          
╠══════════════╬═════════════════════╩═══════════════════╩═════════════════════╣
                 Fail-fast behavior of an iterator cannot be guaranteed      
   Fail-fast   impossible to make any hard guarantees in the presence of     
   behavior              unsynchronized concurrent modification              
╠══════════════╬═══════════════════════════════════════════════════════════════╣
      Is                                                                     
 synchronized               implementation is not synchronized               
╚══════════════╩═══════════════════════════════════════════════════════════════╝

13

เหตุผลที่ใช้กันมากที่สุดHashSetคือการใช้งานคือ (โดยเฉลี่ย) O (1) แทนที่จะเป็น O (log n) หากชุดประกอบด้วยรายการมาตรฐานคุณจะไม่ "ยุ่งกับฟังก์ชันแฮช" ตามที่ได้ทำเพื่อคุณ หากตั้งมีชั้นเรียนที่กำหนดเองคุณต้องใช้hashCodeการใช้งานHashSet(ถึงแม้จะแสดงให้เห็นว่ามีผลบังคับใช้ Java วิธี) แต่ถ้าคุณใช้TreeSetคุณจะต้องทำมันหรืออุปทานComparable Comparatorนี่อาจเป็นปัญหาหากคลาสไม่มีคำสั่งซื้อเฉพาะ

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

ตอนนี้ถ้าคุณต้องการเรียงแล้วก็TreeSetมีความเหมาะสมแม้ว่าถึงแม้จะมีการปรับปรุงบ่อยครั้งและความต้องการผลลัพธ์เรียงไม่บ่อยนักบางครั้งการคัดลอกเนื้อหาไปยังรายการหรืออาร์เรย์และเรียงลำดับได้เร็วขึ้น


จุดข้อมูลใด ๆ สำหรับองค์ประกอบขนาดใหญ่เหล่านี้เช่น 10K ขึ้นไป
kuhajeyan

11

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

เวลาตัดจำหน่ายสามารถอยู่ใกล้กับ O (1) ด้วยต้นไม้สีแดงดำที่ใช้งานได้ถ้าหน่วยความจำทำหน้าที่ฉัน หนังสือของ Okasaki จะมีคำอธิบายที่ดีกว่าที่ฉันสามารถดึงออกมาได้ (หรือดูรายการสิ่งพิมพ์ของเขา )


7

แน่นอนว่าการใช้งาน HashSet นั้นเร็วกว่ามาก - ค่าใช้จ่ายน้อยลงเนื่องจากไม่มีการสั่งซื้อ การวิเคราะห์ที่ดีของการใช้งานการตั้งค่าต่าง ๆ ใน Java มีให้ที่http://java.sun.com/docs/books/tutorial/collections/implementations/set.html

การสนทนาที่นั่นยังชี้ให้เห็นถึงวิธีการ 'ที่อยู่ตรงกลาง' ที่น่าสนใจสำหรับคำถามของ Tree vs Hash Java จัดให้มี LinkedHashSet ซึ่งเป็น HashSet ที่มีรายการเชื่อมโยง "การแทรกที่มุ่งเน้น" ที่เรียกใช้ผ่านนั่นคือองค์ประกอบสุดท้ายในรายการที่เชื่อมโยงนั้นยังถูกแทรกเข้าไปใน Hash ล่าสุดด้วย สิ่งนี้ช่วยให้คุณสามารถหลีกเลี่ยงความยุ่งเหยิงของแฮชที่ไม่มีการเรียงลำดับโดยไม่ทำให้ต้นทุน TreeSet เพิ่มขึ้น


4

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

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


3

ได้รับคำตอบมากมายจากการพิจารณาด้านเทคนิคโดยเฉพาะอย่างยิ่งในเรื่องประสิทธิภาพ ตามที่ฉันเลือกระหว่างTreeSetและHashSetเรื่อง

แต่ฉันอยากจะบอกว่าตัวเลือกควรถูกขับเคลื่อนด้วยการพิจารณาแนวความคิดก่อน หากวัตถุต้องการของคุณเพื่อจัดการสั่งธรรมชาติไม่ได้ทำให้รู้สึกแล้วไม่ได้ใช้

มันเป็นชุดที่เรียงลำดับเนื่องจากการดำเนินการ ดังนั้นจึงหมายความว่าคุณต้องแทนที่ฟังก์ชันซึ่งควรจะสอดคล้องกับสิ่งที่ผลตอบแทนที่ได้ฟังก์ชั่น ตัวอย่างเช่นถ้าคุณมีชุดวัตถุของคลาสที่เรียกว่า Student แล้วฉันไม่คิดว่าTreeSet
SortedSetcompareToequalsTreeSetจะทำให้รู้สึกเนื่องจากไม่มีการเรียงลำดับตามธรรมชาติระหว่างนักเรียน คุณสามารถสั่งซื้อได้ตามเกรดเฉลี่ยของพวกเขาโอเค แต่นี่ไม่ใช่ "การสั่งซื้อตามธรรมชาติ" ฟังก์ชันcompareToจะคืนค่า 0 ไม่เพียง แต่เมื่อวัตถุสองชิ้นเป็นตัวแทนของนักเรียนคนเดียวกัน แต่เมื่อนักเรียนสองคนที่แตกต่างกันมีคะแนนเท่ากัน สำหรับกรณีที่สองequalsจะกลับเท็จ (ถ้าคุณตัดสินใจที่จะทำให้ผลตอบแทนหลังจริงเมื่อนักเรียนสองคนที่แตกต่างกันมีเกรดเดียวซึ่งจะทำให้equalsการทำงานมีความหมายทำให้เข้าใจผิดไม่ได้บอกความหมายผิด.)
โปรดทราบความสอดคล้องระหว่างequalsและcompareToเป็นทางเลือก แต่แนะนำอย่างยิ่ง มิฉะนั้นสัญญาของส่วนต่อประสานSetขาดการทำให้รหัสของคุณทำให้ผู้อื่นเข้าใจผิดดังนั้นอาจนำไปสู่พฤติกรรมที่ไม่คาดคิด

ลิงค์นี้อาจเป็นแหล่งข้อมูลที่ดีเกี่ยวกับคำถามนี้


3

ทำไมต้องมีแอปเปิ้ลเมื่อคุณมีส้ม?

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


1

การแก้ไขข้อความ ( เขียนซ้ำทั้งหมด ) เมื่อคำสั่งซื้อไม่สำคัญนั่นคือเมื่อใด ทั้งคู่ควรให้ Log (n) - เป็นประโยชน์ที่จะได้เห็นว่าเร็วกว่าอีกห้าเปอร์เซ็นต์หรือไม่ HashSet สามารถให้การทดสอบ O (1) ในลูปควรเปิดเผยว่าเป็น


-3
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

public class HashTreeSetCompare {

    //It is generally faster to add elements to the HashSet and then
    //convert the collection to a TreeSet for a duplicate-free sorted
    //Traversal.

    //really? 
    O(Hash + tree set) > O(tree set) ??
    Really???? Why?



    public static void main(String args[]) {

        int size = 80000;
        useHashThenTreeSet(size);
        useTreeSetOnly(size);

    }

    private static void useTreeSetOnly(int size) {

        System.out.println("useTreeSetOnly: ");
        long start = System.currentTimeMillis();
        Set<String> sortedSet = new TreeSet<String>();

        for (int i = 0; i < size; i++) {
            sortedSet.add(i + "");
        }

        //System.out.println(sortedSet);
        long end = System.currentTimeMillis();

        System.out.println("useTreeSetOnly: " + (end - start));
    }

    private static void useHashThenTreeSet(int size) {

        System.out.println("useHashThenTreeSet: ");
        long start = System.currentTimeMillis();
        Set<String> set = new HashSet<String>();

        for (int i = 0; i < size; i++) {
            set.add(i + "");
        }

        Set<String> sortedSet = new TreeSet<String>(set);
        //System.out.println(sortedSet);
        long end = System.currentTimeMillis();

        System.out.println("useHashThenTreeSet: " + (end - start));
    }
}

1
โพสต์กล่าวว่าโดยทั่วไปจะเร็วกว่าในการเพิ่มองค์ประกอบลงใน HashSet แล้วแปลงคอลเลกชันเป็น TreeSet เพื่อการสำรวจเส้นทางที่ไม่มีการเรียงซ้ำ ตั้ง <String> s = new TreeSet <String> (hashSet); ฉันสงสัยว่าทำไมไม่ตั้ง <String> s = new TreeSet <String> () โดยตรงถ้าเรารู้ว่ามันจะถูกใช้สำหรับการเรียงลำดับการวนซ้ำดังนั้นฉันจึงทำการเปรียบเทียบนี้และผลลัพธ์แสดงว่าเร็วกว่าใด
gli00001

"ในกรณีใดบ้างที่ฉันต้องการใช้ HashSet บนชุดต้นไม้"
Austin Henley

1
ประเด็นของฉันคือถ้าคุณต้องการสั่งซื้อให้ใช้ TreeSet เพียงอย่างเดียวดีกว่าใส่ทุกอย่างลงใน HashSet จากนั้นสร้าง TreeSet ตาม HashSet นั้น ฉันไม่เห็นคุณค่าของ HashSet + TreeSet เลยจากโพสต์ต้นฉบับ
gli00001

@ gli00001: คุณพลาดจุดนี้ไป หากคุณไม่ต้องการเรียงลำดับองค์ประกอบของคุณเสมอไป แต่กำลังจะจัดการมันบ่อยๆมันจะคุ้มค่าที่คุณจะใช้แฮชเซ็ตเพื่อรับประโยชน์จากการทำงานที่รวดเร็วขึ้นเกือบตลอดเวลา สำหรับบางครั้งเวลาที่คุณต้องการในการประมวลผลองค์ประกอบในการสั่งซื้อแล้วก็ห่อด้วย TreeSet มันขึ้นอยู่กับกรณีการใช้งานของคุณ แต่นั่นไม่ใช่กรณีการใช้งานแบบไม่ จำกัด จำนวนมาก (และอาจถือว่าชุดที่ไม่มีองค์ประกอบมากเกินไปและมีกฎการสั่งซื้อที่ซับซ้อน)
เฮย์เล็ม
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.