166

它们之间有什么区别?我知道

LinkedHashSet 是 HashSet 的有序版本,它在所有元素中维护一个双向链表。当您关心迭代顺序时,请使用此类而不是 HashSet。当您遍历 HashSet 时,顺序是不可预测的,而 LinkedHashSet 允许您按照元素插入的顺序遍历元素。

但是在 LinkedHashSet 的源代码中,只有调用 HashSet 的构造函数。那么双链表和插入顺序在哪里呢?

4

10 回答 10

68

答案在于使用哪些构造函数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);
}
于 2011-02-22T16:10:46.820 回答
33

HashSet无序无序的Set。
LinkedHashSet是 HashSet 的有序版本

HashSetLinkedHashSet唯一的区别是:
LinkedHashSet维护了插入顺序。

当我们遍历一个HashSet时,顺序是不可预测的,而在LinkedHashSet的情况下它是可预测的。

LinkedHashSet维护插入顺序的原因是:
底层使用的数据结构是双链表

于 2016-07-01T09:33:23.493 回答
25

LinkedHashSet的构造函数调用以下基类构造函数:

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

如您所见,内部映射是一个LinkedHashMap. 如果您查看内部LinkedHashMap,您会发现以下字段:

private transient Entry<K, V> header;

这是有问题的链表。

于 2011-02-22T16:11:48.760 回答
12

我建议你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

您可以在此处查看源测试页面:最终性能测试示例

于 2017-02-16T09:07:44.387 回答
9

您应该查看HashSet它调用的构造函数的来源......它是一个特殊的构造函数,它使支持MapaLinkedHashMap而不仅仅是 a HashMap

于 2011-02-22T16:09:11.890 回答
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()产生先进先出顺序。

于 2013-12-19T19:19:56.963 回答
3

哈希集:

下划线的数据结构是Hashtable。不允许重复的对象。插入顺序不保留,它基于对象的哈希码。可以进行空值插入(仅一次)。它实现了 Serializable、Clonable 但不是 RandomAccess 接口。如果频繁操作是搜索操作,最好选择HashSet。

在 HashSet 中不允许重复。如果用户在尝试插入重复项时我们不会得到任何编译或运行时异常。add 方法只返回 false。

构造函数:

HashSet h=new HashSet(); 创建一个空的 HashSet 对象,默认初始容量为 16 ,默认填充率(负载因子)为 0.75 。

HashSet h=new HashSet(int initialCapacity); 创建一个具有指定 initialCapacity 的空 HashSet 对象,默认填充率为 0.75。

HashSet h=new HashSet(int initialCapacity, float fillRatio);

HashSet h=new HashSet(集合 c); 为给定的集合创建一个等效的 HashSet 对象。此构造函数用于集合对象之间的相互转换。

链接哈希集:

它是 HashSet 的子类。除了以下区别外,它与 HashSet 完全相同,包括(构造函数和方法)。

HashSet 的区别:

  1. 下划线的数据结构是Hashtable。
  2. 不保留广告订单。
  3. 推出1.2版本。

链接哈希集:

  1. 下划线的数据结构是 LinkedList 和 Hashtable 的组合。
  2. 保留插入顺序。
  3. 在 1.4 版本中引入。
于 2017-11-24T16:47:07.177 回答
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
于 2018-04-26T10:16:45.687 回答
1

如果您查看从LinkedHashSet该类调用的构造函数,您会发现在内部它LinkedHashMap是用于支持目的的。

于 2011-02-22T16:12:12.947 回答
0

所有方法和构造函数都是相同的,但唯一不同的是 LinkedHashset 将保持插入顺序,但不允许重复。

Hashset 不会维护任何插入顺序。它是 List 和 Set 的简单组合 :)

于 2016-08-21T12:24:20.523 回答