Java TreeMap 源码解析

2023-11-16

Java TreeMap 源码解析


上篇文章介绍完了HashMap,这篇文章开始介绍Map系列另一个比较重要的类TreeMap
大家也许能感觉到,网络上介绍HashMap的文章比较多,但是介绍TreeMap反而不那么多,这里面是有原因:一方面HashMap的使用场景比较多;二是相对于HashMap来说,TreeMap所用到的数据结构更为复杂。

废话不多说,进入正题。

签名(signature)

      
      
1
2
3
      
      
public classTreeMap<K,V>
extends AbstractMap< K, V>
implements NavigableMap< K, V>, Cloneable, java. io. Serializable

可以看到,相比HashMap来说,TreeMap多继承了一个接口NavigableMap,也就是这个接口,决定了TreeMap与HashMap的不同:

HashMap的key是无序的,TreeMap的key是有序的

接口NavigableMap

首先看下NavigableMap的签名

      
      
1
      
      
public interfaceNavigableMap<K,V> extendsSortedMap<K,V>

发现NavigableMap继承了SortedMap,再看SortedMap的签名

SortedMap

      
      
1
      
      
public interfaceSortedMap<K,V> extendsMap<K,V>

SortedMap就像其名字那样,说明这个Map是有序的。这个顺序一般是指由Comparable接口提供的keys的自然序(natural ordering),或者也可以在创建SortedMap实例时,指定一个Comparator来决定。
当我们在用集合视角(collection views,与HashMap一样,也是由entrySet、keySet与values方法提供)来迭代(iterate)一个SortedMap实例时会体现出key的顺序。

这里引申下关于Comparable与Comparator的区别(参考这里):

  • Comparable一般表示类的自然序,比如定义一个Student类,学号为默认排序
  • Comparator一般表示类在某种场合下的特殊分类,需要定制化排序。比如现在想按照Student类的age来排序

插入SortedMap中的key的类类都必须继承Comparable类(或指定一个comparator),这样才能确定如何比较(通过k1.compareTo(k2)comparator.compare(k1, k2))两个key,否则,在插入时,会报ClassCastException的异常。

此为,SortedMap中key的顺序性应该与equals方法保持一致。也就是说k1.compareTo(k2)comparator.compare(k1, k2)为true时,k1.equals(k2)也应该为true。

介绍完了SortedMap,再来回到我们的NavigableMap上面来。
NavigableMap是JDK1.6新增的,在SortedMap的基础上,增加了一些“导航方法”(navigation methods)来返回与搜索目标最近的元素。例如下面这些方法:

  • lowerEntry,返回所有比给定Map.Entry小的元素
  • floorEntry,返回所有比给定Map.Entry小或相等的元素
  • ceilingEntry,返回所有比给定Map.Entry大或相等的元素
  • higherEntry,返回所有比给定Map.Entry大的元素

设计理念(design concept)

红黑树(Red–black tree)

TreeMap是用红黑树作为基础实现的,红黑树是一种二叉搜索树,让我们在一起回忆下二叉搜索树的一些性质

二叉搜索树

先看看二叉搜索树(binary search tree,BST)长什么样呢?


二叉搜索树 二叉搜索树

相信大家对这个图都不陌生,关键点是:

左子树的值小于根节点,右子树的值大于根节点。

二叉搜索树的优势在于每进行一次判断就是能将问题的规模减少一半,所以如果二叉搜索树是平衡的话,查找元素的时间复杂度为log(n),也就是树的高度。

我这里想到一个比较严肃的问题,如果说二叉搜索树将问题规模减少了一半,那么三叉搜索树不就将问题规模减少了三分之二,这不是更好嘛,以此类推,我们还可以有四叉搜索树,五叉搜索树……对于更一般的情况:

n个元素,K叉树搜索树的K为多少时效率是最好的?K=2时吗?

K 叉搜索树

如果大家按照我上面分析,很可能也陷入一个误区,就是

三叉搜索树在将问题规模减少三分之二时,所需比较操作的次数是两次(二叉搜索树再将问题规模减少一半时,只需要一次比较操作)

我们不能把这两次给忽略了,对于更一般的情况:

n个元素,K叉树搜索树需要的平均比较次数为k*log(n/k)

对于极端情况k=n时,K叉树就转化为了线性表了,复杂度也就是O(n)了,如果用数学角度来解这个问题,相当于:

n为固定值时,k取何值时,k*log(n/k)的取值最小?

k*log(n/k)根据对数的运算规则可以转化为ln(n)*k/ln(k)ln(n)为常数,所以相当于取k/ln(k)的极小值。这个问题对于大一刚学高数的人来说再简单不过了,我们这里直接看结果

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

Java TreeMap 源码解析 的相关文章

  • java中的csv到pdf文件

    我正在尝试获得一个csv文件解析为pdf 到目前为止我所拥有的内容附在下面 我的问题是这段代码最终出现在 pdf 中的文件在 csv 文件的第一行被截断 我不明白为什么 附示例 本质上我想要一个没有任何操作的 csv 文件的 pdf 版本
  • Java 创建浮雕(红/蓝图像)

    我正在编写一个 Java 游戏引擎 http victoryengine org http victoryengine org 并且我一直在尝试生成具有深度的 3D 图像 您可以使用那些红色 蓝色眼镜看到 我正在使用 Java2D 进行图形
  • 通过 InjectMocks Spy 注入对象

    我需要对一个类运行一系列单元测试 该类具有 Autowired Logger 实现 实现的基本思想是 Mock Logger logger InjectMocks TestedClass tested 但我想保存日志输出功能 Mockito
  • 如何对 IntStream 进行逆序排序

    我正在使用 txt 文件读取数字BufferedReader 我想颠倒该流中元素的顺序 以便在收集它们时 它们将从最高到最低排列 我不想在构建数组后进行排序 因为我不知道其中可能有多少元素 我只需要最高的 N 个元素 in new Buff
  • 使用 Spring 时实例化对象,用于测试与生产

    使用 Spring 时 应该使用 Spring 配置 xml 来实例化生产对象 并在测试时直接实例化对象 这样的理解是否正确 Eg MyMain java package org world hello import org springf
  • JavaFX - setVisible 隐藏元素但不重新排列相邻节点

    在 JavaFX 中 如果我有一个场景有 2VBox元素和每个VBox有多个Label in it 如果我设置顶部VBox to 无形的 为什么底部VBox 不向上移动顶部的场景VBox was The VBox is 无形的但我希望其他物
  • Java 变量的作用域

    我不明白为什么这段代码的输出是10 package uno public class A int x 10 A int x 12 new B public static void main String args int x 11 new
  • Spring Stomp over Websocket:流式传输大文件

    我的SockJs客户端在网页中 发送帧大小为16K的消息 消息大小限制决定了我可以传输的文件的最大大小 以下是我在文档中找到的内容 Configure the maximum size for an incoming sub protoco
  • 场景生成器删除 fxml 文件中的导入

    我使用场景构建器 Gluon Scene Builder JavaFX Scene Builder 8 1 1 来创建应用程序的 UI 并使用 Eclipse 开发 JavaFX 现在 每次我在场景生成器中保存某些内容时 它都会从 fxml
  • 使用 Java 在浏览器中下载 CSV 文件

    我正在尝试在 Web 应用程序上添加一个按钮 单击该按钮会下载一个 CSV 文件 该文件很小 大小仅约 4KB 我已经制作了按钮并附加了一个侦听器 文件也准备好了 我现在唯一需要做的就是创建单击按钮时下载 csv 文件的实际事件 假设 fi
  • 所有junit测试后的清理

    在我的项目中 我必须在所有测试之前进行一些存储库设置 这是使用一些棘手的静态规则来完成的 然而 在所有测试之后我不知道如何进行清理 我不想保留一些神奇的静态数字来引用所有测试方法的数量 我应该一直维护它 最受赞赏的方法是添加一些侦听器 该侦
  • cucumber-junit-platform-engine 中的功能文件发现

    In cucumber junit我使用的库 CucumberOptions定义功能文件位置 package com mycompany cucumber import cucumber api CucumberOptions import
  • 想要开发像 Facebook 这样的网站 - 处理数百万个请求 - 高性能 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想用 Java 开发一个像 Fac
  • @EnableTransactionManagement 的范围是什么?

    我试图了解正确的放置位置 EnableTransactionManagement多个 JavaConfig 上下文的情况下的注释 考虑以下场景 我在 JPAConfig java 和 AppConfig java 中有 JPA 配置以及一组
  • Java:VM 如何在 32 位处理器上处理 64 位“long”

    JVM 如何在 32 位处理器上处理 64 位的原始 long 在多核 32 位机器上可以并行利用多个核心吗 64 位操作在 32 位机器上慢了多少 它可能使用多个核心来运行不同的线程 但不会并行使用它们进行 64 位计算 64 位长基本上
  • 参数动态时如何构建 JPQL 查询?

    我想知道是否有一个好的解决方案来构建基于过滤器的 JPQL 查询 我的查询太 富有表现力 我无法使用 Criteria 就像是 query Select from Ent if parameter null query WHERE fiel
  • 阻止 OSX 变音符号为所有用户禁用 Java 中的 KeyBindings?

    注 我知道这个问题 https stackoverflow com questions 40335285 java keybinds stop working after holding down a key用户必须输入终端命令才能解决此问
  • 从java中的字符串数组中删除空值

    java中如何从字符串数组中删除空值 String firstArray test1 test2 test4 我需要像这样没有 null 空 值的 firstArray String firstArray test1 test2 test4
  • Spock模拟inputStream导致无限循环

    我有一个代码 gridFSFile inputStream bytes 当我尝试这样测试时 given def inputStream Mock InputStream def gridFSDBFile Mock GridFSDBFile
  • 尝试使用带有有效购买令牌的 Java Google Play Developer API v3 检索应用内购买信息时出现错误请求(无效值)

    当使用 Java Google Play Developer API 版本 3 并请求有效购买令牌的购买信息时 我收到以下异常 API 调用返回 400 Bad Request 响应以及以下消息 code 400 errors domain

随机推荐

  • 闲谈IPv6-源IP地址的选择(RFC3484读后感)

    杭州数月的连续淅淅沥沥的雨 让我感到舒适 但却不知湿了多少人的皮鞋 回想起2014年的一个周末从上海来杭州 我在思考一个关于IPv6的问题 但一切却不是因为IPv6而起 缘起 在多年以前 我被一个看似很简单的问题困扰了很久很久 问题是这样的
  • 【Zotero高效知识管理】(2)Zotero的安装、百度云存储配置及常用插件安装

    Zotero高效知识管理 专栏其他文章 Zotero文献管理软件的系统性教程 包括安装 全面的配置 基于众多插件的文献导入 管理 引用 笔记方法 Zotero高效知识管理 1 Zotero介绍 Zotero高效知识管理 3 Zotero的文
  • 王爽《汇编语言》第3版 实验4 详解 以及个人的一些小疑问

    实验四 1和2编程 向内存0 2000 23F依次传送数据063 3FH 为什么0 200和0020 0表示的是同一段内存地址 0000 X 16 0200 00200 assume cs codes codes segment mov a
  • android组件之DrawerLayout(抽屉导航)-- 侧滑菜单效果

    一 介绍 导航抽 屉显示 在屏幕的最左侧 默认情况下是隐藏的 当用户用手指从边缘向另一个滑动的时候 会出现一个隐藏的面板 当点击面板外部或者向原来的方向滑动的时候 抽屉导航就会消失了 好了 这个抽屉就是DrawerLayout 该类位于V4
  • MyBatis总结(六)--typeAliases属性介绍

    说明 typeAliases别名处理器 是为 Java 类型设置一个短的名字 可以方便我们 引用某个类 正常情况下不推荐使用该别名处理器 因为使用了别明处理器不方便直接观察到所对应的类 在项目维护起来不方便 1对单个类起别名 在mybati
  • windows10专业版使用远程桌面

    windows企业版远程桌面控制方法 服务器端 打开服务器开关 添加新用户 添加其他用户即可 3 点立即查找 添加要控制的用户 客户端 搜windows远程桌面 添加远程的ip地址即可 家庭想被控制的方法 windows10 远程桌面设置
  • Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60

    文章目录 一 Sentinel简介 1 1 官方文档 1 2 项目地址 1 3 特征 1 4 Sentinel 分为两个部分 1 5 基本概念 1 6 主要作用 流量控制 熔断降级 系统负载保护 1 7 Hystrix 与 Sentinel
  • 机器学习——KNN实现

    一 KNN K近邻 概述 KNN一种基于距离的计算的分类和回归的方法 其主要过程为 计算训练样本和测试样本中每个样本点的距离 常见的距离度量有欧式距离 马氏距离等 对上面所有的距离值进行排序 升序 选前k个最小距离的样本 根据这k个样本的标
  • web信息收集----网站指纹识别

    文章目录 一 网站指纹 web指纹 二 CMS简介 三 指纹识别方法 3 1 在线网站识别 3 2 工具识别 3 3 手动识别 3 4 Wappalyzer插件识别 一 网站指纹 web指纹 Web指纹定义 Web指纹是一种对目标网站的识别
  • Stata改变变量label

    我们用dta格式数据时 label栏可能是无法识别的字符 其中一个原因是我们电脑安装的是简体中文版 但数据原来的label是繁体字 只要用 label var命令就可以更改了 具体用法 label var 变量名称 变量新label 如下所
  • 好像还挺好玩的GAN8——SRGAN实现图像的分辨率提升

    好像还挺好玩的GAN8 SRGAN实现图像的分辨率提升 注意事项 学习前言 什么是SRGAN 代码与训练数据的下载 神经网络组成 1 生成网络 2 判别网络 训练思路 1 对判别模型进行训练 2 对生成模型进行训练 全部代码 1 data
  • JS+CSS实现一个文字跟随屏幕滑动渐入渐出效果

    效果展示 可以看到文字随着屏幕滑动条的滚动逐渐渐入渐出 接下来看看我是怎么实现的把 实现原理 要实现这个效果也很简单 就是利用background image属性的linear gradient给文字加上渐变背景 然后设置backgroun
  • npm、yarn、pnpm如何清除缓存?

    前端工程化创建项目会经常使用各种安装包管理工具 安装各种前端依赖包 例如 npm yarn pnpm等 时间一长 各种安装包管理工具的在安装依赖时 留下的缓存文件就会变得很大 以至于影响系统的运行 因此必要时清除缓存就是一个不错的选择 本文
  • 磁盘调度算法(FCFS、SSTF)例题

    一 原理 先来先服务 FCFS first come first service 根据进程请求访问磁盘的先后次序进行调度 最短寻道时间优先 SSTF Shortest Seek Time First 选择访问的磁道与当前磁头所在的磁道距离最
  • 下列不是HTML网页开发工具的是,网页开发工具有哪些

    越来越多的移动端和桌面端应用开始使用HTML CSS和JS来开发了 而网页设计更是离不开这些语言所需要的工具 下面由小编为大家整理的网页开发工具 希望大家喜欢 网页开发工具 1 Prepo Prepo 是一款同时登录Mac和iOS平台的应用
  • 变分推断

    变分推断是近年来深度学习中一个非常重要的技术手段 推断困难通常是指难以计算p h v 或其期望 其中v指的是模型的可观测变量 而h表示隐藏变量 在深度神经网络中 多层的隐藏变量之间联系复杂 无法通过一个具体地概率密度函数来刻画隐藏变量的实际
  • 微信小程序wx.getUserProfile的用法

    接触了以前开发的一个微信小程序 发现wx getUserInfo这个官方接口不能获取用户的信息 我重新创建了一个新的项目 发现可以用wx getUserProfile这个官方接口来获取用户信息 具体操作如下 1 首先在xxxx jslim里
  • transformer的学习记录【完整代码+详细注释】(系列二)

    文章目录 1 编码器部分实现 1 1 掩码张量 1 1 1 用 np triu 生产上三角矩阵 1 1 2 生成掩码张量的代码 1 1 3 掩码张量可视化展示 1 1 4 掩码张量学习总结 1 2 注意力机制 1 2 1 注意力机制 vs
  • QT6.4制作动态组织架构图

    最近项目需要用QT开发组织架构图 本来先网上找个demo拿来即用 但是找了一圈 要么不能编译 要么运行崩溃 要么很粗糙什么细节都没做 离实际应用差距甚远 于是我自己重新编写调试 耗费几天时间 在Window10 X64上运行 五层级别 右键
  • Java TreeMap 源码解析

    Java TreeMap 源码解析 继上篇文章介绍完了HashMap 这篇文章开始介绍Map系列另一个比较重要的类TreeMap 大家也许能感觉到 网络上介绍HashMap的文章比较多 但是介绍TreeMap反而不那么多 这里面是有原因 一