HashSet vs LinkedHashSet
他们之间有什么区别? 我知道
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.
但是在LinkedHashSet的源代码中,只有HashSet的调用构造函数。 那么双链接列表和插入顺序在哪里?
答案在于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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); } |
并且(一个例子)描述了一个带有布尔参数的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /** * 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); } |
1 2 3 | HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<E, Object>(initialCapacity, loadFactor); } |
如您所见,内部地图是
1 | private transient Entry<K, V> header; |
这是有问题的链表。
HashSet是无序和未排序的Set。 LinkedHashSet是HashSet的有序版本.HashSet和LinkedHashSet之间的唯一区别是LinkedHashSet维护插入顺序。当我们遍历HashSet时,顺序是不可预测的,而在LinkedHashSet的情况下它是可预测的。
LinkedHashSet维护插入顺序的原因是底层数据结构是双向链表。
您应该查看它调用的
我建议你大部分时间都使用
Performance tests:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | ------------- 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 |
您可以在此处查看源测试页面:最终性能测试示例
例
1 2 3 4 5 6 7 |
1 2 3 | 1 ab 2 |
1 2 3 | 2 1 ab |
HashSet的:
实际上是无序的。
如果你通过参数意味着
1 2 3 4 5 | Set<Integer> set=new HashSet<Integer>(); for(int i=0;i<set.length;i++) { SOP(set)`enter code here` } |
出局:
可能
HashSet的:
带下划线的数据结构是Hashtable。
不允许重复的对象。不保留插入顺序,它基于对象的哈希码。
空插入是可能的(只有一次)。
它实现了Serializable,Clonable但不是RandomAccess接口。
如果频繁操作是搜索操作,HashSet最好选择。
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.
构造函数:
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:
它是HashSet的子类。它与HashSet完全相同,包括(构造函数和方法),但以下差异除外。
差异
HashSet的:
LinkedHashSet:
如果你看一下从
所有方法和构造函数都相同,但只有一个区别是LinkedHashset将维护插入顺序,但不允许重复。
Hashset不会维护任何插入顺序。
它是List和Set简单的组合:)