我调查了LinkedHashSet
和HashSet
个收藏品。
我写了一个小程序:
public class LHSTest {
public static void main(String[] args){
output(test(new LinkedHashSet()));
System.out.println("=========");
output(test(new HashSet()));
}
public static HashSet<MyClass> test(HashSet hashSet){
hashSet.add(new MyClass(1));
hashSet.add(new MyClass(2));
hashSet.add(new MyClass(3));
hashSet.add(new MyClass(4));
hashSet.add(new MyClass(5));
return hashSet;
}
public static void output(HashSet hashSet){
for(Iterator iterator = hashSet.iterator();iterator.hasNext();){
System.out.println(iterator.next());
}
}
}
class MyClass{
int a;
MyClass(int a){
this.a =a;
}
public int hashCode(){
return 15-a;
}
public String toString() {
return a+"";
}
}
输出:
1
2
3
4
5
=========
5
4
3
2
1
当我看到这种行为时,我开始研究集合的源代码。
我注意到LinkedHashSet和HashSet都使用
常见toString()
实现 - 来自AbstractCollection
iterator()
的和常见HashSet
我的代码中LinkedHashSet
和HashSet
的不同输出是什么解释?
对于LinkedHashSet
和HashSet
调用不同的构造函数:
代表LinkedHashSet
-
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);
}
代表HashSet
-
public HashSet() {
map = new HashMap<E,Object>();
}
HashMap
和 - LinkedHasMap
的迭代器(来自HashSet
)
public Iterator<E> iterator() {
return map.keySet().iterator();
}
研究keySet()
方法:
HashMap
:
public Set<K> keySet() {
Set<K> ks = keySet;
return (ks != null ? ks : (keySet = new KeySet()));
}
LinkedHashMap
无法特别实现keySet
方法并使用HashMap
实现。
map.keySet().iterator() is
:
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable{
...
private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public Iterator<Map.Entry<K,V>> iterator() {
return newEntryIterator();
}
...
}
...
}
map.keySet()
返回HashMap
和LinkedHashMap
的相同类型,因此会调用相同的newEntryIterator()
方法。
这是错误的陈述吗?
我导航到HashSet#iterator
:
答案 0 :(得分:0)
LinkedHashSet 维护插入顺序,但 HashSet 不会。引自 LinkedHashSet 的javadoc:
Set接口的哈希表和链表实现,具有可预测的迭代顺序。此实现与HashSet的不同之处在于它维护了一个贯穿其所有条目的双向链表。此链接列表定义迭代排序,即元素插入集合(插入顺序)的顺序。
LinkedHashSet 的任何构造函数都会调用 HashSet 的超级构造函数:
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
LinkedHashMap 是 Map 接口的哈希表和链表实现,具有可预测的迭代顺序。
答案 1 :(得分:0)
你没有深入挖掘。
HashSet.iterator()
返回map.keySet().iterator()
map.keySet()
返回HashMap.KeySet
HashMap.KeySet.iterator()
来电[HashMap.this.]newKeyIterator()
LinkedHashMap
会覆盖newKeyIterator().