0

我调查LinkedHashSetHashSet 收藏。

我写了一个小程序:

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

是什么解释了我的代码LinkedHashSetHashSet在我的代码中的不同输出?

伊万·巴巴宁回答后更新

对于LinkedHashSetHashSet调用不同的构造函数:

对于 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()返回相同的类型HashMapLinkedHashMap因此调用相同的newEntryIterator()方法。

是错误的说法吗?

用于 EJP 更新

我导航到HashSet#iterator

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

4

2 回答 2

0

LinkedHashSet维护插入顺序,但HashSet没有。引用LinkedHashSet的 javadoc:

Set 接口的哈希表和链表实现,具有可预测的迭代顺序。此实现与 HashSet 的不同之处在于它维护一个双向链表,该列表贯穿其所有条目。该链表定义了迭代顺序,即元素插入集合的顺序(插入顺序)。

LinkedHashSet的任何构造函数都会调用HashSet的超级构造函数:

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

LinkedHashMap是Map接口的哈希表和链表实现,具有可预测的迭代顺序。

于 2014-04-18T05:54:58.683 回答
0

你没有挖得很深。

  • HashSet.iterator()返回map.keySet().iterator()
  • map.keySet()返回一个HashMap.KeySet
  • HashMap.KeySet.iterator()来电[HashMap.this.]newKeyIterator()
  • LinkedHashMap覆盖newKeyIterator().
于 2014-04-18T07:38:01.193 回答