HashSet vs LinkedHashSet
他们有什么区别? 我知道
LinkedHashSet是HashSet的有序版本,它在所有元素之间维护一个双向链表。 当您关心迭代顺序时,请使用此类而不是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); }
LinkedHashSet
的构造函数调用以下基类构造函数:
HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<E, Object>(initialCapacity, loadFactor); }
正如你所看到的,内部映射是一个LinkedHashMap
。 如果您查看LinkedHashMap
内部,您将发现以下字段:
private transient Entry<K, V> header;
这是有问题的链表。
你应该看看它调用的HashSet
构造函数的源代码…这是一个特殊的构造函数,它使后端Map
一个LinkedHashMap
而不仅仅是一个HashMap
。
HashSet是无序的和未sorting的Set。 LinkedHashSet是HashSet的有序版本.HashSet和LinkedHashSet的唯一区别是LinkedHashSet维护了插入顺序。 当我们遍历一个HashSet时,顺序是不可预知的,而在LinkedHashSet的情况下它是可预测的。 LinkedHashSet维护插入顺序的原因是因为底层数据结构是一个双向链表。
HashSet:实际上是无序的。 如果你传递参数的意思
Set<Integer> set=new HashSet<Integer>(); for(int i=0;i<set.length;i++) { SOP(set)`enter code here` }
输出:可能是2,1,3
不可预测的。 下次再下单。
生成FIFO顺序的LinkedHashSet()
。
我build议大部分时间使用LinkedHashSet
,因为它总体上具有更好的性能 ):
- 可预测的 迭代顺序LinkedHashSet(Oracle)
- LinkedHashSet比HashSet更昂贵的插入;
- 一般来说,性能比
HashMap
稍好一些,因为大部分时间我们都使用Set结构进行迭代。
性能testing:
------------- 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
您可以在这里看到源testing页面: 最终性能testing示例
如果您看一下LinkedHashSet
类中调用的构造函数,您将在内部看到它是一个用于支持目的的LinkedHashMap
。
所有的方法和构造函数是相同的,但只有一个区别是LinkedHashset将维护插入顺序,但不会允许重复。
哈希将不会维护任何插入顺序。 它是List和Set的简单组合:)