HashSet 与 LinkedHashSet

发布于 2024-10-18 14:27:03 字数 261 浏览 3 评论 0原文

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

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

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

What is the difference between them? I know that

A LinkedHashSet is an ordered version of HashSet that
maintains a doubly-linked List across all elements. Use this class instead of HashSet
when you care about the iteration order. When you iterate through a HashSet the
order is unpredictable, while a LinkedHashSet lets you iterate through the elements
in the order in which they were inserted.

But in sourcecode of LinkedHashSet there are only calling constructors of HashSet. So where is double-linked List and insertion order?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

哀由 2024-10-25 14:27:04

HashSet无序未排序的集合。
LinkedHashSet 是 HashSet 的有序版本

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

当我们迭代HashSet时,顺序是不可预测的,而LinkedHashSet的顺序是可预测的。

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

HashSet is unordered and unsorted Set.
LinkedHashSet is the ordered version of HashSet.

The only difference between HashSet and LinkedHashSet is that:
LinkedHashSet maintains the insertion order.

When we iterate through a HashSet, the order is unpredictable while it is predictable in case of LinkedHashSet.

The reason for how LinkedHashSet maintains insertion order is that:
The underlying used data structure is Doubly-Linked-List.

时间你老了 2024-10-25 14:27:04

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

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

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

private transient Entry<K, V> header;

这是有问题的链接列表。

LinkedHashSet's constructors invoke the following base class constructor:

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

As you can see, the internal map is a LinkedHashMap. If you look inside LinkedHashMap, you'll discover the following field:

private transient Entry<K, V> header;

This is the linked list in question.

猫瑾少女 2024-10-25 14:27:04

我建议您大多数时候使用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

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

I suggest you to use LinkedHashSet most of the time, because it has better performance overall):

  1. Predictable iteration order LinkedHashSet (Oracle)
  2. LinkedHashSet is more expensive for insertions than HashSet;
  3. In general slightly better performance than HashMap, because the most of the time we use Set structures for iterating.

Performance tests:

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

You can see source test page here: The Final Performance Testing Example

有深☉意 2024-10-25 14:27:04

您应该查看它调用的 HashSet 构造函数的源代码...它是一个特殊的构造函数,使支持 Map 成为 LinkedHashMap 而不仅仅是一个HashMap

You should look at the source of the HashSet constructor it calls... it's a special constructor that makes the backing Map a LinkedHashMap instead of just a HashMap.

能否归途做我良人 2024-10-25 14:27:04

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

HashSet don't maintain the order of insertion item
LinkedHashSet maintain the order of insertion item

Example

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 output

1
ab
2

LinkedHashSet output

2
1
ab
饭团 2024-10-25 14:27:04

哈希集:
实际上是无序的。
如果你传递参数意味着

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

Out Put:
可能2,1,3不可预测。下次再下单。

LinkedHashSet() 产生 FIFO 顺序。

HashSet:
Unordered actually.
if u passing the parameter means

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

Out Put:
May be 2,1,3 not predictable. next time another order.

LinkedHashSet() which produce FIFO Order.

我不吻晚风 2024-10-25 14:27:04

HashSet:

下划线的数据结构是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 对象。该构造函数用于集合对象之间的相互转换。

LinkedHashSet:

它是HashSet的子类。它与 HashSet 完全相同,包括(构造函数和方法),但有以下差异。

差异
HashSet:

  1. 下划线的数据结构就是Hashtable。
  2. 不保留插入顺序。
  3. 推出1.2版本。

LinkedHashSet:

  1. 下划线的数据结构是LinkedList和Hashtable的组合。
  2. 保留插入顺序。
  3. 1.4版本引入。

HashSet:

The underlined data structure is Hashtable.
Duplicate objects are not allowed.insertion order is not preserved and it is based on hash code of objects.
Null insertion is possible(only once).
It implements Serializable, Clonable but not RandomAccess interface.
HashSet is best choose if frequent operation is search operation.

In HashSet duplicates are not allowed.if users are trying to insert duplicates when we won't get any compile or runtime exceptions. add method returns simply false.

Constructors:

HashSet h=new HashSet(); creates an empty HashSet object with default initial capacity 16 and default fill ratio(Load factor) is 0.75 .

HashSet h=new HashSet(int initialCapacity); creates an empty HashSet object with specified initialCapacity and default fill ration is 0.75.

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

HashSet h=new HashSet(Collection c); creates an equivalent HashSet object for the given collection. This constructor meant for inter conversion between collection object.

LinkedHashSet:

It is a child class of HashSet. it is exactly same as HashSet including(Constructors and Methods) except the following differences.

Differences
HashSet:

  1. The underlined data structure is Hashtable.
  2. Insertion order is not preserved.
  3. introduced 1.2 version.

LinkedHashSet:

  1. The underlined data structure is a combination of LinkedList and Hashtable.
  2. Insertion order is preserved.
  3. Indroduced in 1.4 version.
ㄖ落Θ余辉 2024-10-25 14:27:04

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

If you take a look at the constructors called from the LinkedHashSet class you will see that internally it's a LinkedHashMap that is used for backing purpose.

执笔绘流年 2024-10-25 14:27:04

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

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

All Methods and constructors are same but only one difference is LinkedHashset will maintain insertion order but it will not allow duplicates.

Hashset will not maintain any insertion order.
It is combination of List and Set simple :)

蓝礼 2024-10-25 14:27:03

正如您所说,两者之间的区别是:

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

至于你的问题:

但是LinkedHashSet的源代码中只有调用HashSet的构造函数。

答案在于 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);
}

The difference between the two are, as you've stated:

A LinkedHashSet is an ordered version of HashSet that maintains a doubly-linked List across all elements. Use this class instead of HashSet when you care about the iteration order. When you iterate through a HashSet the order is unpredictable, while a LinkedHashSet lets you iterate through the elements in the order in which they were inserted.

As for your question:

But in sourcecode of LinkedHashSet there are only calling constructors of HashSet.

The answer lies in which constructors the LinkedHashSet uses to construct the base class:

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

And (one example of) a HashSet constructor that takes a boolean argument is described, and looks like this:

/**
 * 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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文