Hashset vs LinkedHashset


153

sự khác biệt giữa chúng là gì? tôi biết điều đó

LinkedHashset là phiên bản được đặt hàng của Hashset duy trì Danh sách liên kết đôi trên tất cả các yếu tố. Sử dụng lớp này thay vì Hashset khi bạn quan tâm đến thứ tự lặp. Khi bạn lặp qua Hashset, thứ tự không thể đoán trước được, trong khi LinkedHashset cho phép bạn lặp qua các phần tử theo thứ tự chúng được chèn.

Nhưng trong mã nguồn của LinkedHashset chỉ có các hàm tạo của Hashset. Vậy đâu là Danh sách liên kết kép và thứ tự chèn?


2
sử dụng tùy chọn Intellij (Ctrl + B) để theo dõi câu trả lời. :)
Delta

tất nhiên bạn cần mã nguồn đính kèm. :)
Delta

Câu trả lời:


65

Những lời nói dối câu trả lời trong đó nhà xây dựng các LinkedHashSetcông dụng để xây dựng các lớp cơ sở:

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);
}

Và (một ví dụ về) một hàm HashSettạo lấy một đối số boolean được mô tả và trông như thế này:

/**
 * 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
Một lớp cha có chức năng rõ ràng cho một lớp con, một đối số bị bỏ qua để phân biệt
Traubenfuchs

5
Không chính xác một thiết kế sạch sẽ sử dụng một tham số giả cho định hướng xây dựng.
Eric J.

7
Đây là thiết kế hợp lý sạch, vì API sạch (hàm tạo Hashset này là gói riêng tư). Các chi tiết thực hiện không quan trọng đối với người dùng của lớp. Việc duy trì mã này có thể khó hơn, nhưng trong trường hợp các lớp java.util, ngay cả những cải tiến hiệu suất rất nhỏ cũng có thể biện minh cho điều đó.
lbalazscs

25

LinkedHashSetCác constructor của inv gọi hàm tạo của lớp cơ sở sau:

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

Như bạn có thể thấy, bản đồ nội bộ là a LinkedHashMap. Nếu bạn nhìn vào bên trong LinkedHashMap, bạn sẽ khám phá trường sau:

private transient Entry<K, V> header;

Đây là danh sách liên kết trong câu hỏi.


24

HashSetkhông có thứ tựkhông được phân loại Set.
LinkedHashSetphiên bản được đặt hàng của Hashset.

Sự khác biệt duy nhất giữa HashsetLinkedHashset là:
LinkedHashSet duy trì thứ tự chèn.

Khi chúng tôi lặp lại thông qua Hashset , thứ tự không thể đoán trước trong khi có thể dự đoán được trong trường hợp LinkedHashset .

Lý do cho cách LinkedHashset duy trì thứ tự chèn là:
Cấu trúc dữ liệu được sử dụng cơ bản là Danh sách liên kết đôi .


9

Bạn nên xem xét nguồn gốc của các HashSetnhà xây dựng nó gọi ... đó là một nhà xây dựng đặc biệt mà làm cho sự ủng hộ Mapmột LinkedHashMapthay vì chỉ một HashMap.


Cảm ơn, trong Hashset có hàm tạo để tạo LinkedHashMap, được gọi trong LinkedHashset và tất cả logic nằm trong LinkedHashMap
Shikarn-O

5

Tôi khuyên bạn nên sử dụng LinkedHashSethầu hết thời gian, vì nó có hiệu suất tổng thể tốt hơn ):

  1. Thứ tự lặp có thể dự đoán được LinkedHashset (Oracle)
  2. LinkedHashSet đắt hơn khi chèn thêm so với Hashset;
  3. Nói chung hiệu năng tốt hơn một chút HashMap, bởi vì phần lớn thời gian chúng tôi sử dụng Cấu trúc đặt để lặp lại.

Kiểm tra hiệu năng:

------------- 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

Bạn có thể xem trang kiểm tra nguồn tại đây: Ví dụ kiểm tra hiệu suất cuối cùng


2
Tôi không thấy JVM nóng lên trước những "điểm chuẩn" đó, vì vậy tôi sẽ không xem trọng bất kỳ dữ liệu nào. Đọc thêm
Felix S

3

Hashset: Thực sự không có thứ tự. nếu bạn truyền tham số nghĩa là

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

Ra ngoài: Có thể 2,1,3không dự đoán được. lần sau đặt hàng khác.

LinkedHashSet() nơi sản xuất đơn hàng FIFO.


3

HashSet không duy trì thứ tự của mục chèn
LinkedHashSet duy trì thứ tự của mục chèn

Thí dụ

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 đầu ra

1
ab
2

LinkedHashSet đầu ra

2
1
ab

2

Hashset:

Cấu trúc dữ liệu được gạch chân là Hashtable. Các đối tượng trùng lặp không được phép. Thứ tự chèn không được bảo toàn và nó dựa trên mã băm của các đối tượng. Không thể chèn Null (chỉ một lần). Nó thực hiện giao diện serializable, Clonable nhưng không phải RandomAccess. Hashset là lựa chọn tốt nhất nếu hoạt động thường xuyên là hoạt động tìm kiếm.

Trong Hashset, các bản sao không được phép. Nếu người dùng đang cố gắng chèn các bản sao khi chúng tôi sẽ không nhận được bất kỳ ngoại lệ biên dịch hoặc thời gian chạy nào. thêm phương thức trả về đơn giản là sai.

Người xây dựng:

Hashset h = new Hashset (); tạo một đối tượng Hashset trống với dung lượng ban đầu mặc định 16 và tỷ lệ lấp đầy mặc định (hệ số tải) là 0,75.

Hashset h = new Hashset (int initCapacity); tạo một đối tượng Hashset trống với initCapacity được chỉ định và tỷ lệ điền mặc định là 0,75.

Hashset h = new Hashset (int initCapacity, float fillRatio);

Hashset h = new Hashset (Bộ sưu tập c); tạo một đối tượng Hashset tương đương cho bộ sưu tập đã cho. Hàm tạo này có nghĩa là để chuyển đổi giữa các đối tượng bộ sưu tập.

LinkedHashset:

Đây là một lớp con của Hashset. nó hoàn toàn giống với Hashset bao gồm (Trình xây dựng và Phương thức) ngoại trừ những khác biệt sau.

Sự khác biệt Hashset:

  1. Cấu trúc dữ liệu được gạch chân là Hashtable.
  2. Thứ tự chèn không được bảo quản.
  3. giới thiệu phiên bản 1.2.

LinkedHashset:

  1. Cấu trúc dữ liệu được gạch chân là sự kết hợp của LinkedList và Hashtable.
  2. Thứ tự chèn được bảo tồn.
  3. Được sản xuất trong phiên bản 1.4.

1

Nếu bạn nhìn vào các hàm tạo được gọi từ LinkedHashSetlớp, bạn sẽ thấy rằng bên trong nó LinkedHashMapđược sử dụng cho mục đích sao lưu.


0

Tất cả các Phương thức và hàm tạo đều giống nhau nhưng chỉ có một điểm khác biệt là LinkedHashset sẽ duy trì thứ tự chèn nhưng nó sẽ không cho phép trùng lặp.

Hashset sẽ không duy trì bất kỳ thứ tự chèn nào. Nó là sự kết hợp của List và Set đơn giản :)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.