Hashmaps、Treemaps和LinkedHashmaps在Java中是如何工作的?

Hashmaps、Treemaps和LinkedHashmaps在Java中是如何工作的?,java,hashmap,treemap,linkedhashmap,Java,Hashmap,Treemap,Linkedhashmap,我对地图有各种各样的问题: 迭代Hashmap时,无法保证迭代顺序。为什么呢 为什么哈希映射比树映射快 LinkedHashMaps是如何工作的,它们是如何维持秩序的?是不是因为他们有一个双链接列表,其中包含关于在条目之前和之后存储哪个条目的信息 我一直在阅读API文档,但由于我是一个编程新手,所以在理解它时遇到了一些困难 要保持简短: 地图和集合通常是未排序的数据结构。如果您想要“排序集”,可能最好使用列表或数组 您的问题更多的是关于数据结构,而不是一个真正特定的或与java相关的编程问题,因

我对地图有各种各样的问题:

  • 迭代Hashmap时,无法保证迭代顺序。为什么呢
  • 为什么哈希映射比树映射快
  • LinkedHashMaps是如何工作的,它们是如何维持秩序的?是不是因为他们有一个双链接列表,其中包含关于在条目之前和之后存储哪个条目的信息
  • 我一直在阅读API文档,但由于我是一个编程新手,所以在理解它时遇到了一些困难

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

    您的问题更多的是关于数据结构,而不是一个真正特定的或与java相关的编程问题,因此,您应该从阅读Those开始。 (很抱歉作为答案发布:评论问题需要50次重复)

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

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

    例如,假设我们有一个散列函数h(x),它为字符串“Hello”返回127,为“Zebra”返回12。如果我们将这些键输入到散列图中,那么它们的读取顺序是“Zebra”->(不管附加了什么值),然后是“Hello”->(不管附加了什么值)

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

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    
    请注意,这是散列的实际作用和表示形式的简化变体。可能是哈希值发生冲突,需要以某种方式解决该冲突。这意味着作为底漆;密钥是按其散列顺序插入的,但是如果您的散列函数有缺陷,或者您的对象的散列值不好,那么您可能会遇到异常行为

    为什么哈希映射比树映射快

    哈希操作不依赖于整个集合的大小。回想一下,h(x)仅基于我们尝试插入的单个值进行操作。如果我们将元素插入到<代码> TeeMeP中,我们必须考虑它们的自然排序,这涉及遍历结构以找到插入的点,并且还涉及重新平衡或重新组织结构,以确保平衡被保留。 对于
    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;
    }
    
    public V put(K键,V值){
    条目t=根;
    如果(t==null){
    比较(key,key);//类型(可能为null)检查
    root=新条目(键、值、空);
    尺寸=1;
    modCount++;
    返回null;
    }
    int-cmp;
    进入父母;
    //拆分比较器和可比较路径
    
    比较您应该更具体地说明您不了解的内容。我们可能会给您提供与您之前没有得到的相同的解释。您需要查看数据结构。有上千种资源将详细介绍每种结构的工作原理。作为入门,您可以阅读和,以便您了解哈希表/映射和二进制tr是如何工作的ees(特别是TreeMap使用的红黑树)一般来说。至于第三个问题,答案是:是的。:)可能重复的@Madhan:这不是一个完全重复的问题。至少,我觉得它不是一个。你应该在评论中这样说。这不是一个有效的答案。这是一个建议,没有详细说明。你还把排序和排序混为一谈。a
    HashMap
    HashSet
    总体上是无序的,但这并不是说你不能对数据进行排序(甚至排序)。也不是这样,例如TreeMap vs HashMap,TreeSet vs HashSet。另外,如果你需要一个集合,为什么要使用列表或数组?集合中的成员是O(1)或O(LogN)对于集合类。使用列表和数组作为集合只是一个坏主意。如果我们将这些值输入到哈希映射中。你是说将哈希值输入到
    哈希映射
    还是
    字符串
    值中?你是指键而不是值吗?让我来澄清一下。这些应该是键,而不是值。