HashSet vs LinkedHashSet


154

ความแตกต่างระหว่างพวกเขาคืออะไร? ฉันรู้แล้ว

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

แต่ใน sourcecode ของ LinkedHashSet มีเพียงการเรียก constructors ของ HashSet เท่านั้น รายการที่ถูกเชื่อมโยงสองครั้งและลำดับการแทรกอยู่ที่ไหน


2
ใช้ตัวเลือก Intellij (Ctrl + B) เพื่อติดตามคำตอบ :)
เดลต้า

แน่นอนคุณต้องแนบซอร์สโค้ด :)
เดลต้า

คำตอบ:


65

คำตอบอยู่ในที่ก่อสร้างLinkedHashSetใช้ในการสร้างชั้นฐาน:

public LinkedHashSet(int initialCapacity, float loadFactor) {
    super(initialCapacity, loadFactor, true);      // <-- boolean dummy argument
}

...

public LinkedHashSet(int initialCapacity) {
    super(initialCapacity, .75f, true);            // <-- boolean dummy argument
}

...

public LinkedHashSet() {
    super(16, .75f, true);                         // <-- boolean dummy argument
}

...

public LinkedHashSet(Collection<? extends E> c) {
    super(Math.max(2*c.size(), 11), .75f, true);   // <-- boolean dummy argument
    addAll(c);
}

และ (ตัวอย่างหนึ่ง) คอนHashSetสตรัคเตอร์ที่รับอาร์กิวเมนต์บูลีนถูกอธิบายและมีลักษณะดังนี้:

/**
 * Constructs a new, empty linked hash set.  (This package private
 * constructor is only used by LinkedHashSet.) The backing
 * HashMap instance is a LinkedHashMap with the specified initial
 * capacity and the specified load factor.
 *
 * @param      initialCapacity   the initial capacity of the hash map
 * @param      loadFactor        the load factor of the hash map
 * @param      dummy             ignored (distinguishes this
 *             constructor from other int, float constructor.)
 * @throws     IllegalArgumentException if the initial capacity is less
 *             than zero, or if the load factor is nonpositive
 */
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);
}

2
ชั้นผู้ปกครองที่มีฟังก์ชั่นอย่างชัดเจนสำหรับชั้นเรียนเด็กอาร์กิวเมนต์ที่ไม่สนใจที่จะแยกแยะความแตกต่าง
Traubenfuchs

5
ไม่ใช่การออกแบบที่สะอาดหมดจดโดยใช้พารามิเตอร์ดัมมี่สำหรับคอนดัคเตอร์
Eric J.

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

25

LinkedHashSetConstructor ของเรียกใช้ Constructor คลาสฐานต่อไปนี้:

HashSet(int initialCapacity, float loadFactor, boolean dummy) {
  map = new LinkedHashMap<E, Object>(initialCapacity, loadFactor);
}

LinkedHashMapในขณะที่คุณสามารถดูแผนที่ภายในจะเป็น หากคุณมองเข้าไปข้างในLinkedHashMapคุณจะค้นพบฟิลด์ต่อไปนี้:

private transient Entry<K, V> header;

นี่คือรายการเชื่อมโยงที่มีปัญหา


24

HashSetคือเรียงลำดับและไม่ได้เรียงลำดับชุด
LinkedHashSetเป็นรุ่นที่สั่งซื้อของ HashSet

ความแตกต่างเพียงอย่างเดียวระหว่างHashSetและLinkedHashSetคือ:
LinkedHashSet จะรักษาลำดับการแทรก

เมื่อเราย้ำผ่านHashSet , สั่งซื้อสินค้าจะไม่แน่นอนในขณะที่มันเป็นที่คาดหมายในกรณีของLinkedHashSet

เหตุผลสำหรับวิธีการLinkedHashSetรักษาเพื่อแทรกคือ:
โครงสร้างข้อมูลพื้นฐานที่ใช้เป็นทวีคูณที่เชื่อมโยงรายชื่อ


9

คุณควรดูที่แหล่งที่มาของHashSetคอนสตรัคที่เรียกว่า ... มันเป็นคอนสตรัคพิเศษที่ทำให้การสนับสนุนแทนเพียงMapLinkedHashMapHashMap


ขอบคุณใน HashSet มีตัวสร้างสำหรับการสร้าง LinkedHashMap ซึ่งเรียกว่าใน LinkedHashSet และตรรกะทั้งหมดอยู่ใน LinkedHashMap
Shikarn-O

6

ฉันแนะนำให้คุณใช้LinkedHashSetเวลาส่วนใหญ่เพราะมันมีประสิทธิภาพโดยรวมที่ดีกว่า ):

  1. คำสั่งการทำซ้ำที่คาดการณ์ได้LinkedHashSet (Oracle)
  2. LinkedHashSet มีราคาแพงกว่าการแทรกมากกว่า HashSet;
  3. โดยทั่วไปประสิทธิภาพที่ดีขึ้นเล็กน้อยกว่าHashMapเพราะส่วนใหญ่เราใช้ Set โครงสร้างสำหรับการวนซ้ำ

การทดสอบประสิทธิภาพ:

------------- TreeSet -------------
 size       add  contains   iterate
   10       746       173        89
  100       501       264        68
 1000       714       410        69
10000      1975       552        69
------------- HashSet -------------
 size       add  contains   iterate
   10       308        91        94
  100       178        75        73
 1000       216       110        72
10000       711       215       100
---------- LinkedHashSet ----------
 size       add  contains   iterate
   10       350        65        83
  100       270        74        55
 1000       303       111        54
10000      1615       256        58

คุณสามารถดูหน้าทดสอบต้นฉบับได้ที่นี่: ตัวอย่างการทดสอบประสิทธิภาพขั้นสุดท้าย


2
ฉันไม่เห็นว่า JVM อุ่นขึ้นก่อนหน้า "มาตรฐาน" ดังนั้นฉันจะไม่ใช้ข้อมูลเหล่านั้นอย่างจริงจัง อ่านเพิ่มเติม
Felix S

3

HashSet: ไม่มีการเรียงลำดับจริง ๆ ถ้าคุณผ่านพารามิเตอร์หมายถึง

Set<Integer> set=new HashSet<Integer>();
for(int i=0;i<set.length;i++)
{
  SOP(set)`enter code here`
}

เอาท์: อาจ2,1,3ไม่สามารถคาดเดาได้ ครั้งต่อไปที่คำสั่งอื่น

LinkedHashSet() ซึ่งผลิตคำสั่ง FIFO


3

HashSet ไม่รักษาลำดับของรายการที่แทรก
LinkedHashSet ไว้รักษาลำดับของรายการที่แทรก

ตัวอย่าง

Set<String> set = ...;// using new HashSet<>() OR new LinkedHashSet<>()
set.add("2");
set.add("1");
set.add("ab");
for(String value : set){
   System.out.println(value);
}  

HashSet เอาท์พุต

1
ab
2

LinkedHashSet เอาท์พุต

2
1
ab

2

HashSet:

โครงสร้างข้อมูลที่ขีดเส้นใต้คือ Hashtable วัตถุที่ซ้ำกันไม่ได้รับอนุญาตลำดับการตรวจสอบจะไม่ถูกสงวนไว้และขึ้นอยู่กับรหัสแฮชของวัตถุ สามารถแทรก Null ได้ (เพียงครั้งเดียว) มันใช้อินเตอร์เฟส Serializable, Clonable แต่ไม่ใช่ RandomAccess HashSet เป็นทางเลือกที่ดีที่สุดหากการใช้งานบ่อยครั้งคือการค้นหา

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

ก่อสร้าง:

HashSet h = new HashSet (); สร้างวัตถุ HashSet ที่ว่างเปล่าด้วยความจุเริ่มต้นเริ่มต้น 16 และอัตราส่วนการเติมเริ่มต้น (ตัวประกอบการโหลด) คือ 0.75

HashSet h = ใหม่ HashSet (int initialCapacity); สร้างวัตถุ HashSet ที่ว่างเปล่าที่มี initialCapacity ที่ระบุและปันส่วนเติมเริ่มต้นคือ 0.75

HashSet h = HashSet ใหม่ (int initialCapacity, float fillRatio);

HashSet h = HashSet ใหม่ (คอลเล็กชัน c); สร้างวัตถุ HashSet ที่เทียบเท่าสำหรับคอลเลกชันที่กำหนด คอนสตรัคนี้มีความหมายสำหรับการแปลงระหว่างวัตถุการเก็บรวบรวม

LinkedHashSet:

มันเป็นคลาสลูกของ HashSet มันเหมือนกับ HashSet ซึ่งรวมถึง (Constructors และ Methods) ยกเว้นความแตกต่างดังต่อไปนี้

HashSet ที่แตกต่าง:

  1. โครงสร้างข้อมูลที่ขีดเส้นใต้คือ Hashtable
  2. คำสั่งแทรกไม่ได้รับการเก็บรักษาไว้
  3. แนะนำรุ่น 1.2

LinkedHashSet:

  1. โครงสร้างข้อมูลที่ขีดเส้นใต้เป็นการรวมกันของ LinkedList และ Hashtable
  2. ลำดับการแทรกถูกสงวนไว้
  3. indroduced ในรุ่น 1.4

1

ถ้าคุณดูคอนสตรัคเตอร์ที่เรียกจากLinkedHashSetคลาสคุณจะเห็นว่าภายในมันเป็นของLinkedHashMapที่ใช้สำหรับการสำรองข้อมูล


0

เมธอดและตัวสร้างทั้งหมดเหมือนกัน แต่ความแตกต่างเพียงอย่างเดียวคือ LinkedHashset จะรักษาลำดับการแทรก แต่จะไม่อนุญาตให้ทำซ้ำ

Hashset จะไม่รักษาการเรียงลำดับการแทรกใด ๆ มันคือการรวมกันของรายการและตั้งง่าย :)

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