Hashmap、Treemap 和 LinkedHashmap 在 Java 中如何工作?

2023-11-29

我对地图有各种疑问:

  1. 迭代 Hashmap 时,无法保证迭代顺序。这是为什么呢?
  2. 为什么 Hashmap 比 Treemap 更快?
  3. LinkedHashMap 是如何工作的,它们如何维护顺序?是因为它们有一个双向链表,其中包含有关哪个条目存储在条目之前和之后的信息吗?

我一直在阅读 API 文档,但由于我是编程的初学者,所以在理解它时遇到了一些困难。


迭代 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);
}

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

为什么 Hashmap 比 Treemap 更快?

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

有一个lot更多信息来源TreeMap's put method.

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;
}

LinkedHashMap 是如何工作的,它们如何维护顺序?是因为它们有一个双向链表,其中包含有关哪个条目存储在条目之前和之后的信息吗?

你可以自己阅读源码,但这里的主要要点是:

  • 键仍然以哈希结构分组在一起,以确保其唯一性。
  • 它们的插入顺序由 FIFO 结构(如链表)保存。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Hashmap、Treemap 和 LinkedHashmap 在 Java 中如何工作? 的相关文章

随机推荐

  • 脚本动画块 iOS

    我正在尝试制作一系列全屏图像的动画 每个图像将以不同的方式进行动画处理 我想将这些动画存储在数据库或 plist 或其他任何地方 我只是不想对它们进行硬编码 动画将非常简单 图像中的对象会抖动或弹跳或发生什么 我将使用块对对象进行动画处理
  • 从 Swift 使用 C API

    我正在尝试跟踪网络状态 我浏览了代码外汇可达性 具体有以下方法 void setHost NSString host if host host if reachability SCNetworkReachabilityUnscheduleF
  • C :将有符号转换为无符号

    实际上我 可能 有一个 简单 的问题 所以我不知道如何将有符号整数转换为无符号整数 我的代码 signed int entry 0 printf Decimal Number scanf d entry unsigned int uEntr
  • 防止列表推导式中除以零

    我有以下代码 scores matrix i i sum matrix i for i scores in enumerate matrix 我的问题是sum matrix i 在某些情况下可能为 0 从而导致ZeroDivisionErr
  • 如何在 OpenAPI 中定义嵌套数组?

    我想定义这个 locationPoly 87 63466 24 50182 80 03074 24 50182 80 03074 31 00107 87 63466 31 00107 87 63466 24 50182 在我的 OpenAP
  • 计算同一字符的最大子串数

    我想编写一个函数 其中它接收一个字符串和一个字母 该函数需要返回该字母的最长子串的长度 我不知道为什么我写的函数不起作用 例如 print count longest repetition eabbaaaacccaaddd a 应该返回 4
  • 将 Keycloak Spring 适配器与 Spring Boot 3 结合使用

    我在一个使用 Keycloak Spring Adapter 的项目中更新到了 Spring Boot 3 不幸的是 它没有启动 因为KeycloakWebSecurityConfigurerAdapter extends WebSecur
  • 结构测试:可识别与类测试:可识别

    struct Test Identifiable 导致错误 类型 测试 不符合协议 可识别 它需要 id 属性 class Test Identifiable 编译没有任何问题 Why From SE 0261 可识别协议 强调我的 为了尽
  • 如何配置 Xcode 项目以使用 TestFlightApp 进行 Beta 测试?

    我注册了 TestFlight 然后我按照中的所有步骤进行操作本教程 但是 Xcode 会抛出这个警告 应用程序未通过协同设计验证 签名无效 包含不允许的权利 或者不是用 iPhone 签名的 经销证书 19011 听起来好像还有比他们在教
  • Android 中检测 VoLTE 通话

    我对 Android 中由 LTE 运营商提供的 VoLTE 服务知之甚少 Android 中是否有可用于检测 VoLTE 通话的 API API例如 呼叫已接通 呼叫已断开 Latency 通话状态 非常感谢任何链接 API 参考 Tel
  • 当您在用户注册时自动创建子域时,它会创建一个新网站还是提供一个网站的外观? [关闭]

    Closed 这个问题是基于意见的 目前不接受答案 我想知道注册时创建的子域是否会成为网站 或者它们是否只是给人一种错觉 认为它们是类似于 example com username 的网站 我正在尝试创建类似 user domain com
  • jQuery 交叉淡入淡出插件

    我正在尝试构建或实现标题 图像旋转器 用户将单击一个数字 1 2 3 图像将淡出 淡入 并根据所选数字进行标题更改 跨度元素中的某些文本 是否有现有插件可以执行此操作 如果没有 使用 jQuery 实现此目的的最佳方法是什么 Thanks
  • Sed/Awk 在文件中搜索和替换/插入文本

    我正在尝试更新或插入一些注释 例如版权标头到目录 Linux 中的所有源文件中 我的文件不一致 因此其中一些文件已经有标题 而其他文件则根本没有 我尝试过sed查看前几行并替换 替换我的意思是用最新的文件更改已经具有版权标头的文件 sed
  • 响应式 SVG 视图框

    我在 SVG 中制作了一个 汉堡按钮 如下所示 body margin 0 text align center svg ham btn margin 2rem border 1px solid black fill 383838
  • 带信号量的线程安全单例问题

    我编写了一个简单的单例应用程序 以下是我的示例主类 ThreadsafeSingletonUsingSemaphore cpp Defines the entry point for the console application incl
  • initMap 不是一个函数

    我不明白有什么问题 我使用了 Google Map API 中的这个示例 简单地图 section section main js
  • Java程序执行一个命令需要很长时间

    我阅读了很多示例 最终使用以下代码从 Java 程序内部执行命令行命令 public static void executeCommand final String command throws IOException Interrupte
  • Javadoc 中文本文件(资源)的链接

    我进行了搜索 但找不到正确的答案 如何在 Javadoc 中使用指向资源文本文件的链接 link easywords txt 不起作用 a href Easy words a 也不行 Try a href Easy words a 反而 链
  • 使用 C# 为通过 Gmail 发送的邮件设置不同的“发件人”地址

    我正在使用一个简单的邮件发送器类 该类使用System Net Mail 我需要更新我的应用程序 以便各个用户可以通过它发送电子邮件 使用相同的 smtp 帐户 但 发件人 地址应该是导致发送电子邮件的用户的地址 我尝试设置From的财产M
  • Hashmap、Treemap 和 LinkedHashmap 在 Java 中如何工作?

    我对地图有各种疑问 迭代 Hashmap 时 无法保证迭代顺序 这是为什么呢 为什么 Hashmap 比 Treemap 更快 LinkedHashMap 是如何工作的 它们如何维护顺序 是因为它们有一个双向链表 其中包含有关哪个条目存储在