JDK 8 TreeMap 源码解析

论文阅读笔记:Extended Vision Transformer (ExViT) for Land Use and Land Cover Classification 注意力机制驱动的深度模型最近取得了成功,如最具代表性的视觉转换器(ViT),吸引了一波高级研究来探索它们对更广泛领域的适应。然而,遥感(RS)领域中基于Transformer的方法更关注单模态数据,这可能会在充分利用不断增长的多模态地球观测数据时失去可扩展性。为此,我们提出了一种新的多模式深度学习框架,通过在最小修改的情况下扩展传统的ViT,针对土地利用和土地覆盖(LULC)分类任务。 阅读详情

【本文是为了梳理知识的总结性文章,总结了一些自认为相关的重要知识点,只为巩固记忆以及技术交流,忘批评指正。其中参考了很多前辈的文章,包括图片也是引用,如有冒犯,侵删。】

0 存储结构

TreeMap 是一个有序的Map,内部按照Key的排序结果来组织。一般如果没有需要排序的情况下,我们都使用HashMap或者多线程下使用ConcurrentHashMap,因为TreeMap的插入和删除的效率没有前两者高。但是如果需要有序的Map,那么就只能选TreeMap了,HashMap是基于Hash散列的,因此是无序的。从底层实现来看,TreeMap 是基于红黑树实现的,在学习之前需要先了解红黑树的基础知识,可以参考数据结构之红黑树Java实现。

1 类定义

public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable

2 红黑树节点Entry结构

// 使用boolean值表示红黑树节点颜色
    private static final boolean RED   = false;
    private static final boolean BLACK = true;
    
    static final class Entry<K,V> implements Map.Entry<K,V> {
        K key;              
        V value;
        Entry<K,V> left;    // 左子树
        Entry<K,V> right;   // 右子树
        Entry<K,V> parent;  // 父节点
        boolean color = BLACK; // 节点颜色

        Entry(K key, V value, Entry<K,V> parent) {
            this.key = key;
            this.value = value;
            this.parent = parent;
        }

        public K getKey() {
            return key;
        }

        public V getValue() {
            return value;
        }

        public V setValue(V value) {
            V oldValue = this.value;
            this.value = value;
            return oldValue;
        }

        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;

            return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
        }

        public int hashCode() {
            int keyHash = (key==null ? 0 : key.hashCode());
            int valueHash = (value==null ? 0 : value.hashCode());
            return keyHash ^ valueHash;
        }

        public String toString() {
            return key + "=" + value;
        }
    }

3 属性

    /** 
     * 用于维护此TreeMap中顺序的比较器,如果它为null,则使用key的自然顺序。
     */
    private final Comparator<? super K> comparator;
    // 树的根节点
    private transient Entry<K,V> root;

    /**
     * 树中节点的个数
     */
    private transient int size = 0;

    /**
     * 树进行结构性修改的次数
     */
    private transient int modCount = 0;

4 构造函数

主要用于初始化 comparator

    // 默认使用自然排序,插入TreeMap的Key必须实现Comparable接口才能进行比较 
    public TreeMap() {
        comparator = null;
    }

    // 使用指定的比较器,
    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }

    // 基于现有的Map构造TreeMap
    public TreeMap(Map<? extends K, ? extends V> m) {
        comparator = null;
        putAll(m);
    }

    // 构造一个和SortedMap具有相同顺序和元素的新Map
    public TreeMap(SortedMap<K, ? extends V> m) {
        comparator = m.comparator();
        try {
            buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
        } catch (java.io.IOException cannotHappen) {
        } catch (ClassNotFoundException cannotHappen) {
        }
    }

5 常用方法

get(Object key)

     public V get(Object key) {
        // 调用getEntry方法进行查找
        Entry<K,V> p = getEntry(key);
        // 不存在返回null
        return (p==null ? null : p.value);
    }

getEntry方法,无论是基于自定义比较器的查找,还是基于自然排序比较器的比较,都是在二叉树下的查找。当前元素大于目标元素,向左找;当前元素小于目标元素,向右找。

    
    final Entry<K,V> getEntry(Object key) {
        // Offload comparator-based version for sake of performance
        if (comparator != null)
            // 基于指定比较器的比较
            return getEntryUsingComparator(key);
        /* 自然排序比较 */
        if (key == null)
            throw new NullPointerException();
        @SuppressWarnings("unchecked")
            Comparable<? super K> k = (Comparable<? super K>) key;
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = k.compareTo(p.key);
            if (cmp < 0) // 当前元素大于目标元素,向左找
                p = p.left;
            else if (cmp > 0) // 当前元素小于目标元素,向右找
                p = p.right;
            else
                return p;
        }
        return null;
    }

    final Entry<K,V> getEntryUsingComparator(Object key) {
        @SuppressWarnings("unchecked")
            K k = (K) key;
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            Entry<K,V> p = root;
            while (p != null) {
                int cmp = cpr.compare(k, p.key);
                if (cmp < 0)   // 当前元素大于目标元素,向左找
                    p = p.left;
                else if (cmp > 0) // 当前元素小于目标元素,向右找
                    p = p.right;
                else
                    return p;
            }
        }
        return null;
    }

put(K key,V value)

插入时先进行查找,看是否存在相同key的节点,存在就直接替换value,不存的话能找到要插入的位置parent, 构造新节点进行插入,然后调用fixAfterInsertion方法进行插入修复,插入修复设计红黑树的重新着色和旋转,详情见数据结构之红黑树Java实现。

public V put(K key, V value) {
        // 根节点为空的情况
        Entry<K,V> t = root;
        if (t == null) {
            compare(key, key); // 类型检查,有可能为null

            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); // 存在重复的key,直接覆盖,返回旧值
            } 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); // 存在重复的key,直接覆盖,返回旧值
            } while (t != null);
        }
        // 不存在具有相同Key的节点,新建节点进行插入
        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;
    }

remove(Object key)

    public V remove(Object key) {
        // 先找到目标节点    
        Entry<K,V> p = getEntry(key);
        if (p == null)
            return null;

        V oldValue = p.value;
        // 调用deleteEntry进行删除   
        deleteEntry(p);
        return oldValue;
    }

deleteEntry删除方法, 删除过程,可以简单分为4种情况:

  1. 只有一个节点的情况;
  2. 删除点p的左右子树都为空;
  3. 只有一棵子树非空;
  4. 删除点p的左右子树都非空。

对于情况1,直接将根节点root置为null就可以;

对于情况2,直接将p删除,将p的parent指向p的指针置为null;

对于情况3,用非空子树替代p;

对于情况4,可以用p的后继s(树中大于p的最小的那个元素)代替p,然后删除后继s。后继s一定不是左右子树非空,就可以使用情况1、2、3进行处理。

删除修复方法fixAfterDeletion详见,数据结构之红黑树Java实现。

private void deleteEntry(Entry<K,V> p) {
        modCount++;
        size--;

        // If strictly internal, copy successor's element to p and then make p
        // point to successor.
        // 删除节点p的左右子树都非空,将P 指向后继元素
        if (p.left != null && p.right != null) {
            Entry<K,V> s = successor(p); // 寻找后继
            p.key = s.key;
            p.value = s.value;
            p = s;
        } // p has 2 children

        // Start fixup at replacement node, if it exists.
        // 删除点p只有一棵子树非空,从子树中选出替代元素
        Entry<K,V> replacement = (p.left != null ? p.left : p.right);

        if (replacement != null) {
            // Link replacement to parent
            // 替换parent指向
            replacement.parent = p.parent;
            if (p.parent == null)
                root = replacement;
            else if (p == p.parent.left)
                p.parent.left  = replacement;
            else
                p.parent.right = replacement;

            // Null out links so they are OK to use by fixAfterDeletion.
            // 删除P节点
            p.left = p.right = p.parent = null;

            // Fix replacement
            // 插入修复
            if (p.color == BLACK)
                fixAfterDeletion(replacement);
        } else if (p.parent == null) { // 只有一个节点p的情况
            root = null;
        } else { //  删除点p的左右子树都为空
            if (p.color == BLACK)
                fixAfterDeletion(p);

            if (p.parent != null) {
                if (p == p.parent.left)
                    p.parent.left = null;
                else if (p == p.parent.right)
                    p.parent.right = null;
                p.parent = null;
            }
        }
    }

successor(Entry<K,V> t)

寻找后继的方法,对于一棵二叉查找树,给定节点t,其后继(树中比大于t的最小的那个元素)可以通过如下方式找到:

  1. t 的右子树不空,则t的后继是其右子树中最小的那个元素。
  2. t 的右孩子为空,则t的后继是其第一个向左走的祖先。
// 寻找节点后继函数successor()
static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {
    if (t == null)
        return null;
    else if (t.right != null) {// t的右子树不空,则t的后继是其右子树中最小的那个元素
        Entry<K,V> p = t.right;
        while (p.left != null)
            p = p.left;
        return p;
    } else {//  t的右孩子为空,则t的后继是其第一个向左走的祖先
        Entry<K,V> p = t.parent;
        Entry<K,V> ch = t;
        while (p != null && ch == p.right) {
            ch = p;
            p = p.parent;
        }
        return p;
    }
}

TreeMap_successor.png

firstEntry()

寻找第一个节点,根据二叉查找树的性质,树的最做左边的节点最小。

    public Map.Entry<K,V> firstEntry() {
        return exportEntry(getFirstEntry());
    }
    // 树的最左边的是最小值
    final Entry<K,V> getFirstEntry() {
        Entry<K,V> p = root;
        if (p != null)
            while (p.left != null)
                p = p.left;
        return p;
    }
    // 返回简单不可变entry,如果为null,则返回null
    static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) {
        return (e == null) ? null :
            new AbstractMap.SimpleImmutableEntry<>(e);
    }

lastEntry()

返回树的最大的元素,根据二叉查找树的性质,树的最做右边的节点最小。

    public Map.Entry<K,V> lastEntry() {
        return exportEntry(getLastEntry());
    }
    // 找到根节点的最右边节点
    final Entry<K,V> getLastEntry() {
        Entry<K,V> p = root;
        if (p != null)
            while (p.right != null)
                p = p.right;
        return p;
    }

lowerEntry(K key) 

找到刚好小于Key的节点。

    public Map.Entry<K,V> lowerEntry(K key) {
        return exportEntry(getLowerEntry(key));
    }

     final Entry<K,V> getLowerEntry(K key) {
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = compare(key, p.key);
            if (cmp > 0) {
                // key 比当前p.key大
                if (p.right != null)
                    p = p.right; // 向右查找
                else
                    // 比最大的右加点还大,返回最大值
                    return p; 
            } else {
                // key 比当前p.key大
                if (p.left != null) {
                    p = p.left;// 向左查找
                } else {
                    // 比最低的左节点大,向上查找第一个左拐的父节点
                    Entry<K,V> parent = p.parent;
                    Entry<K,V> ch = p;
                    while (parent != null && ch == parent.left) {
                        ch = parent;
                        parent = parent.parent;
                    }
                    return parent;
                }
            }
        }
        return null;
    }

higherEntry(K key)

    public Map.Entry<K,V> higherEntry(K key) {
        return exportEntry(getHigherEntry(key));
    }

     final Entry<K,V> getHigherEntry(K key) {
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = compare(key, p.key);
            if (cmp < 0) {
                // key 比当前p.key小
                if (p.left != null)
                    p = p.left; // 向左查找
                else
                    return p;  // 比最小的左加点还小,返回最小值
            } else {
                // key 比当前p.key大
                if (p.right != null) {
                    p = p.right; // 向右查找
                } else { 
                    // 比最低的右节点大,向上查找第一个右拐的父节点
                    Entry<K,V> parent = p.parent;
                    Entry<K,V> ch = p;
                    while (parent != null && ch == parent.right) {
                        ch = parent;
                        parent = parent.parent;
                    }
                    return parent;
                }
            }
        }
        return null;
    }

......

操作不能完成 (错误 0x00000709) 共享打印机无法连接解决办法 环境:windows Server 2012 + Win10 客户端 问题:使用计算机名和IP地址可以正常连接打印机,但是使用另外的A记录或CN记录无法连接,报此错误 原因:这是打印服务DNS解析的问题 故障补充:假设你的服务器电脑名称叫print01,但是你又建了一条A记录或者CNname 叫PR01,就会发现使用额外的A记录或CN记录就无法连接 故障截图: 操作不能完成 (错误... 阅读详情

相关推荐

GOM引擎单机传奇架设全攻略——从DBC2000配置到登录器生成

本文详细解析了使用GOM引擎架设单机传奇的完整流程,从DBC2000的安装配置、服务端部署、引擎控制器设置,到登录器生成与客户端补丁放置。文章重点解决了单机架设中的常见问题,如数据库路径配置、IP地址设置及Key.lic文件处理,旨在帮助玩家快速搭建稳定的个人游戏环境,体验GM乐趣。

weixin_28318011的博客 627

jdk8源码8---集合7----TreeMap

一、签名 public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable NavigableMap:可导航的Map。 Since 1.6. 它实现继...

方小白 473

Ansys Lumerical FDTD仿真加速策略与高性能硬件选型指南

本文深入探讨了Ansys Lumerical FDTD仿真的核心加速策略,涵盖算法优化与硬件选型两大维度。通过合理运用非均匀网格、对称边界条件等算法技巧,并精准匹配CPU/GPU计算资源与高性能硬件配置,可显著提升仿真效率,将计算时间从数天缩短至数小时。

a0b1c2d3的专栏 605

JDK 8 TreeMap 详解及详细源码展示

摘要: JDK 8 的 TreeMap 是基于红黑树的有序映射表,继承 AbstractMap 并实现 NavigableMap 接口,支持按键的自然顺序或自定义比较器排序。其核心特性包括: 有序性:键按自然顺序或比较器排序,操作时间复杂度为 O(log n)。 键唯一:不允许重复键,默认禁用 null 键(自然排序时)。 导航方法:提供 ceilingKey、floorKey 等高效查找功能。 结构实现: 内部通过红黑树(Entry 节点)维护键值对,包含父/子指针和颜色标记。 构造方法支持自然排序、自定

csdn_tom_168的博客 682

携程酒店数据爬取进阶:动态接口破解与反反爬策略实战

本文详细解析了携程酒店数据爬取的进阶技巧,包括动态接口参数破解、反爬虫策略对抗及企业级采集方案实现。重点介绍了eleven参数的生成逻辑、动态Cookie维护方法,以及如何应对携程的请求指纹检测和行为模式识别。通过实战案例,帮助开发者高效获取酒店价格数据,同时遵守行业规范。

eee77的博客 1078

【测开求职】面试题:操作系统 吐血整理

本篇文章是笔者为准备研究生复试和校招而写,因此主要针对问答,注重理解,而不在于细节计算。涵盖考研范围内的所有知识内容,读者可以先查看上面的链接走一遍操作系统的整体框架结构。其中,重点难点以及易混淆的知识点,笔者用其他文章进行了详述,在知识点处贴好了链接,有需要的可以查阅。另外操作系统在校招中有非常明显的重点,一般情况下只会考察进程管理,内存管理,和设备管理,且这三者考察频率依次递减,文件管理基本不会考察。

vector的博客 7908

Java8集合之TreeMap

//Rotate Left private void rotateLeft(Entry<K,V> p) { if (p != null) { // 记录下p节点的右孩子r,用r的左孩子代替原来的右孩子 Entry<K,V> r = p.right; p.right = r.left; // 新的左孩子与p建立父子关系 if (r.left != null) r.left..

CRUD工程师 1535

运维颠覆!一文解锁AI赋能运维实战秘籍,效率飙升!

将AI应用于运维工作是一场极具价值的变革,从故障预测与诊断到自动化任务执行,再到资源管理优化,AI都展现出巨大潜力。尽管在实践过程中会面临数据质量、模型复杂性等挑战,但通过合理的技术选型和解决方案,我们能够充分挖掘AI的优势,实现运维工作的高效、智能转型。持续探索和创新AI在运维领域的应用,将为企业的数字化发展提供坚实保障。在科技飞速发展的当下,运维领域正经历着深刻变革,AI的融入成为提升运维效率与质量的关键。本文将深入实战,带你领略AI如何在运维各环节大显身手,让你的运维工作开启智能高效新模式。

探索云原生与智能化驱动下的安全运维新范式。关注DevSecOps、可观测性、AIOps等前沿领域,与您共赴技术前沿。 401

TreeMap实现原理及源码分析之JDK8

转载Java 集合系列12之 TreeMap详细介绍(源码解析)和使用示例 一、TreeMap 简单介绍 什么是Map?   在数组中我们通过数组下标来对数组内容进行索引的,而在Map中我们通过对象来对 对象进行索引,用来索引的对象叫做key,其对应的对象叫做value。这就是我们平时说的键值对。 什么是TreeMap?   TreeMap是一个有序的key-value集合,是非线程安...

weixin_30294021的博客 311

诊断测试工具CANoe.DiVa从入门到精通系列——开门见山

### 工具主要用于测试ECU的诊断功能。关于自动化诊断测试可以分为如下内容: ### -> 1、根据诊断需求规范进行cdd文件的编辑(现阶段主要是诊断问卷调查表); ### -> 2、新建Diva工程,导入对应的诊断数据库文件生成测试用例; ### -> 3、新建CANoe工程,导入CANoe.DiVa生成的Diva工程; ### -> 4、根据测试报告进行错误处理。

Soly_kun的博客 3545

基于YOLOv11的手写数字与符号识别系统设计与实现

手写数字与符号识别系统需要丰富多样的训练数据才能达到理想的泛化性能。MNIST:包含70,000个手写数字样本(0-9),28x28灰度图像优点:干净整齐,适合初学者缺点:多样性不足,只有数字EMNIST:MNIST的扩展,包含数字、字母(大小写)和特殊符号样本量:814,255张图像覆盖62个类别(10数字+26小写字母+26大写字母)HASYv2:专门的手写符号数据集包含369个不同符号类别约168,000个标注实例包括数学符号、箭头、括号等:英文手写文本数据库。

YOLO 290

Java8源码-TreeMap

前几天学习了HashMap、Hashtable、LinkedHashMap、WeakHashMap,今天开始学习TreeMap。 TreeMap是Map接口基于红黑树的实现,键值对是有序的。本文主要讲解关于红黑树实现的部分。 部分顶部注释 A Red-Black tree based NavigableMap implementation. The map is sorted ac...

潘威威的博客 2608

基于深度学习YOLOv11的布匹缺陷检测系统(Python+PySide6界面+训练代码)

YOLOv11模型训练:根据布匹缺陷数据集训练YOLOv11模型,以识别布匹中的各种缺陷,如裂纹、污渍、破损等。PySide6界面设计:设计一个图形用户界面,帮助用户上传布匹图像,并显示模型的检测结果。模型优化与精度提升:通过数据增强、超参数调优等手段提高模型的准确性。本文介绍了如何基于YOLOv11实现布匹缺陷检测系统,并通过PySide6构建了一个图形用户界面。该系统能够自动检测布匹中的各种缺陷,具有较高的效率和精度。

斌擎科技 529

TreeMap源码解析(基于JDK1.8)

TreeMap源码解读 目录 一、继承关系 二、基本属性 三、构造方法 四、Entry介绍(红黑树) 1、基本属性与构造方法源码 2、常用方法 put fixAfterInsertion rotateLeft和rotateRight get getEntry getEntryUsingComparator remove deleteEntry fixAfterDeletion方法 deleteEntry删除的流程 ...

stay hungry ! stay foolish! 642

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

TreeMap(JDK1.8)源码解析

文章目录简介概览源码分析查找遍历插入删除总结 简介 TreeMap最早出现在JDK 1.2中,是 Java 集合框架中比较重要一个的实现。TreeMap 底层基于红黑树实现,可保证在log(n)时间复杂度内完成 containsKey、get、put 和 remove 操作,效率很高。另一方面,由于 TreeMap 基于红黑树实现,这为 TreeMap 保持键的有序性打下了基础。总的来说,Tree...

ThinkWon的博客 8825

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

深入TreeMap源码解析(JDK1.8)

TreeMap源码解析(JDK1.8) 1. 概述 Map 接口的实现类 HashMap、LinkedHashMap、TreeMap。本篇来讲一下TreeMap的实现原理。TreeMap 不如 HashMap 那么常用,但存在即合理,它也有自己的应用场景,TreeMap 可以实现元素的自动排序。 TreeMap 底层基于红黑树实现,利用红黑树的性质,实现了键值对排序功能,可以保证元素按 key 值大小进行遍历。 2. 原理 2.1 TreeMap继承关系 TreeMap 继承自 AbstractMap 抽

org_hjh的博客 315

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Java集合-TreeMap源码解析-JDK1.8

◆TreeMap简介◆推荐查看此篇文章之前首先查看HashMap源码分析效果更佳哦TreeMap在jdk 1.8中使用用的是红黑树的结构来进行存储的,一个典型的红黑树...

javaxuexilu的博客 350

TreeMap源码解析 --基于JDK1.8

内部类 static final class Entry<K,V> implements Map.Entry<K,V> { K key; V value; Entry<K,V> left; Entry<K,V> right; Entry<K,V> parent; boolean color = BLACK; /**

qq_41202539的博客 313

Java源码解析之TreeMap(jdk1.8)上篇

前言 今天我们要来啃Map体系中的硬骨头了TreeMap。这个名字听着好熟悉,是的我们在介绍HashMap的时候说过,当链表的长度大于8的时候,链表将会被转换为一个TreeNode。TreeNode使用红黑树的方式来组织数据,TreeMap同理。在我们介绍TreeMap之前,我认为我们有必要彻底的了解一下什么是红黑树:其实它是一种特殊的二叉树,能够提供最坏情况下遍历树的时间——O(logn),而链...

weixin_40606398的博客 598

JDK 8 TreeMap 源码详解(完整版带详细注释)

JDK 8 TreeMap源码采用红黑树实现,是一个基于排序的Map结构。核心实现包括:1)使用Entry节点存储键值对,包含左右子节点、父节点和颜色标记;2)提供自然排序(Comparable)和比较器(Comparator)两种排序方式;3)关键操作方法如get()通过二分查找实现高效查询,put()方法在插入后维护红黑树平衡;4)通过比较器或键的自然顺序维持元素有序性。TreeMap保证了基本操作(get/put/remove)的时间复杂度为O(log n),适用于需要有序键值对的场景。

csdn_tom_168的博客 807

JDK1.8中TreeMap源码解析——红黑树删除

在看本文之前建议先看一下二叉树的删除过程,这里有一篇文章写得不错,可以看一下 1、后继节点 在看源码之前,先说说红黑树寻找 待删除节点t 的 后继节点 的过程: 如果待删除节点t有右节点,那么后继节点为该节点右子树中最左的节点,也就是右子树中值最小的节点 如果待删除节点t无右节点,那么后继节点是向上遍历过程中 第一个向左拐的父节点 图解过程如下: 注:图片来源 该过程对应的TreeMap...

瓜牛呱呱的博客 917

JDK1.8源码阅读记录TreeMap类

JDK1.8源码阅读记录 JAVA.Util包 TreeMap类 说明 public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable TreeMap是基于Navigable接口的红黑...

weixin_43459704的博客 188

JDK8-数据结构-Map以及具体的实现(待更新)

Map 存储一组键值对象,提供key到value的映射。 实现类 java.util.HashMap 数据结构与算法 HashMap用到数组,链表(单链表),树(红黑树)三种数据结构和哈希算法。 static final int hash(Object key) { int h; // 异或运算:0^0=0;0^1=1;1^0=1;1^1=0 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16)

瑾析编程 508

JAVA集合容器源码解析

集合容器是我们使用的最多的一个容器,像ArrayList,LinkList,HashMap等等,这个系列的文章主要从源码来解析比较常用的集合,一方面练习自己阅读源码的能力,另一方面加强对集合容器的理解。 集合容器的关系有如下这张图 当然我不会全部去看,会自己挑几个重点的看。 另外,我觉得看源码要有目的性,你要怎么看,需要看哪些。对于我自己,我主要从以下方面来看源码: 1、类的说明 2、字段 3、主...

tangyuan_sibal的博客 509

java集合知识点总结

-----子接口:Set:存储无序的、不可重复的数据(需要判断hashcode()得到的哈希值以及equals()得 到的boolean型的结果,哈希值相同且equals()返回true,则认为元素是相同的。|---- LinkedList:底层使用双向链表的方式进行存储;4.jdk7数组+单向链表,jdk8数组+单向链表+红黑树,如果数组索引i位置上的元素个数达到8了,并且数组长度达到64了,就会将此索引i位置上的多个元素改为使用红黑树进行存储。

qkfjrbbf的博客 375

JDK源码系列

本篇是总览一下过往中看过的源码。虽然现在想想记住的寥寥无几。 jdk8源码1---String类 https://blog.youkuaiyun.com/wxy540843763/article/details/80640593 jdk8源码2---集合1---ArrayList https://blog.youkuaiyun.com/wxy540843763/article/details...

方小白 537
上一篇: 计算无线信号的传输距离
下一篇: JDK 8 ConcrrentHashMap 源码解析
TaiSung
博客等级 码龄15年 49粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值