Hashmaps,Treemaps和LinkedHashmaps如何在Java中工作?

时间:2015-07-01 17:37:56

标签: java hashmap treemap linkedhashmap

我对地图有各种疑问:

  1. 迭代Hashmap时,无法保证迭代顺序。现在为什么会这样?
  2. 为什么Hashmaps比Treemaps更快?
  3. LinkedHashMaps如何运作,他们如何维护订单?是因为他们有一个双向链表,其中包含有关在条目之前和之后存储哪个条目的信息?
  4. 我一直在阅读API文档,但由于我是初学者,在编程方面我很难理解它。

2 个答案:

答案 0 :(得分:5)

  

迭代Hashmap时,无法保证迭代顺序。那为什么呢?

它们的插入顺序不是它们发生的时间,而是它们散列到的值。

例如,假设我们有一个哈希函数 h(x),它为字符串“Hello”返回127,为“Zebra”返回12。如果我们将这些键输入到我们的哈希映射中,它们被读出的顺序是“Zebra” - > (无论附加什么价值),然后“你好” - > (无论附加什么价值)。

这在HashMap的源代码中很明显:

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

请注意,这是对实际执行和表示的哈希的简化变体。可能是哈希值存在冲突,并且需要以某种方式解决冲突。这是指底漆;密钥是按其哈希的顺序插入的,但是如果你的哈希函数有缺陷或你的对象的哈希没有一个好的值,那么你可能会遇到异常的行为。

  

为什么Hashmaps比Treemaps更快?

哈希操作不依赖于整个集合的大小。回想一下, h(x)仅基于我们试图插入的单个值进行操作。如果我们将元素插入TreeMap,我们必须考虑它们所处的自然顺序 - 这涉及遍历结构以找到要插入的位置,并且还可能涉及重新平衡或重新组织结构以确保保持平衡。

TreeMap put方法的来源还有很多

public V put(K key, V value) {
    Entry<K,V> t = root;
    if (t == null) {
        compare(key, key); // type (and possibly null) check

        root = new Entry<>(key, value, null);
        size = 1;
        modCount++;
        return null;
    }
    int cmp;
    Entry<K,V> parent;
    // split comparator and comparable paths
    Comparator<? super K> cpr = comparator;
    if (cpr != null) {
        do {
            parent = t;
            cmp = cpr.compare(key, t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    else {
        if (key == null)
            throw new NullPointerException();
        @SuppressWarnings("unchecked")
            Comparable<? super K> k = (Comparable<? super K>) key;
        do {
            parent = t;
            cmp = k.compareTo(t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    Entry<K,V> e = new Entry<>(key, value, parent);
    if (cmp < 0)
        parent.left = e;
    else
        parent.right = e;
    fixAfterInsertion(e);
    size++;
    modCount++;
    return null;
}
  

LinkedHashMaps如何运作,他们如何维护订单?是因为它们有一个双向链表,其中包含有关条目前后存储的条目的信息?

You can read the source for yourself,但主要内容是:

  • 密钥仍然以哈希结构组合在一起,以确保它们的唯一性。
  • 它们的插入顺序由FIFO结构保存,如链表。

可以这样想:您使用哈希函数来确保密钥是唯一的,如果是,则立即将其及其值插入列表中。这样,订单和唯一性都得以保留。

答案 1 :(得分:-2)

保持简短: 地图和集合通常是未排序的数据结构。如果你想要“排序集”,你最好使用列表或数组。

您的问题更多是关于数据结构而不是真正具体或与Java相关的编程问题,因此,您应该首先阅读有关数据的内容。 (很抱歉发帖回答:评论问题需要50个代表)