Java TreeMap:基于红黑树的排序映射解析

简介: Java TreeMap:基于红黑树的排序映射解析

在Java的集合框架中,TreeMap是一个非常重要的成员,它实现了SortedMap接口,为键(Key)提供了一个有序的映射。这种有序性是通过红黑树数据结构来实现的,红黑树是一种自平衡的二叉查找树,它能够在最坏的情况下保证基本的动态集合操作(如查找、插入和删除)的时间复杂度仍然是对数的。


1. TreeMap概述


TreeMap存储的键值对默认是按照键的自然顺序进行排序的,也可以根据创建TreeMap时提供的Comparator进行排序。这意味着当你遍历TreeMap时,你会得到一个按键排序的键值对序列。


2. TreeMap的内部结构


红黑树TreeMap实现有序性的关键。红黑树的特性确保了树的平衡,从而在插入、删除和查找操作时都能保持对数级别的时间复杂度。红黑树的每个节点都有一个颜色属性——红色或黑色,并且满足以下性质:

  • 每个节点或是红色,或是黑色。
  • 根节点是黑色。
  • 每个叶子节点(NIL节点,空节点)是黑色。
  • 如果一个节点是红色的,则它的两个子节点都是黑色的。
  • 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。

这些性质确保了树的高度相对较低,从而优化了性能。


3. TreeMap的使用场景


  • 当你需要一个有序的键值对集合时。
  • 当你需要对键进行范围查询时(例如查找所有键在指定范围内的元素)。
  • 当你需要一个能够在插入和删除时保持高效性能的数据结构时。


4. 示例代码


下面是一个简单的示例,展示了如何使用TreeMap

import java.util.TreeMap;
public class TreeMapExample {
    public static void main(String[] args) {
        // 创建一个TreeMap实例,按照键的自然顺序排序
        TreeMap<String, Integer> treeMap = new TreeMap<>();
        
        // 向TreeMap中添加元素
        treeMap.put("apple", 1);
        treeMap.put("orange", 2);
        treeMap.put("banana", 3);
        treeMap.put("pear", 4);
        
        // 遍历并打印TreeMap中的元素(按键的顺序)
        for (Map.Entry<String, Integer> entry : treeMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
        
        // 根据键的范围查询元素(包含起始键,不包含结束键)
        TreeMap<String, Integer> subMap = (TreeMap<String, Integer>) treeMap.subMap("apple", "pear");
        System.out.println("Elements between 'apple' and 'pear':");
        for (Map.Entry<String, Integer> entry : subMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

输出:

apple: 1
banana: 3
orange: 2  # 注意这里的顺序,因为按照字母顺序排序了键
pear: 4    # 同上,尽管在插入时pear是在orange后面的,但在排序后它的顺序改变了
Elements between 'apple' and 'pear':  # 范围查询结果不包括'pear'键对应的元素
apple: 1
banana: 3  # 注意这里只有banana是因为orange不在apple和pear之间(按照字母顺序)

注意:在上面的输出中,你可能会注意到“orange”和“banana”的顺序似乎与插入顺序不同。这是因为TreeMap默认按键的自然顺序(这里是字母顺序)对键进行排序,而不是按照插入顺序。此外,范围查询的结果也是有序的,并且不包括结束键对应的元素。如果你想按照特定的顺序对键进行排序,可以在创建TreeMap时提供一个自定义的Comparator


5. 自定义排序


为了按照自定义的顺序对TreeMap中的键进行排序,可以在创建时传入一个Comparator对象:

import java.util.Comparator;
import java.util.TreeMap;
public class CustomSortedTreeMap {
    public static void main(String[] args) {
        // 创建一个自定义排序的TreeMap实例(按照字符串长度排序)
        TreeMap<String, Integer> treeMap = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return Integer.compare(o1.length(), o2.length());
            }
        });
        
        // 向TreeMap中添加元素并打印(按键的长度顺序)
        treeMap.put("apple", 1);  // 长度为5的键
        treeMap.put("kiwi", 2);   // 长度为4的键
        treeMap.put("pear", 3);   // 长度为4的键
        treeMap.put("banana", 4); // 长度为6的键,会被放在最后面即使它是先被插入的
        for (Map.Entry<String, Integer> entry : treeMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

在这个例子中,我们提供了一个自定义的Comparator来按照字符串的长度对键进行排序。因此,“kiwi”和“pear”(长度为4)将出现在“apple”(长度为5)之前,“banana”(长度为6)将出现在最后,即使它是第一个被插入的元素。

相关文章
|
7月前
|
机器学习/深度学习 JSON Java
Java调用Python的5种实用方案:从简单到进阶的全场景解析
在机器学习与大数据融合背景下,Java与Python协同开发成为企业常见需求。本文通过真实案例解析5种主流调用方案,涵盖脚本调用到微服务架构,助力开发者根据业务场景选择最优方案,提升开发效率与系统性能。
1733 0
|
7月前
|
Java
Java的CAS机制深度解析
CAS(Compare-And-Swap)是并发编程中的原子操作,用于实现多线程环境下的无锁数据同步。它通过比较内存值与预期值,决定是否更新值,从而避免锁的使用。CAS广泛应用于Java的原子类和并发包中,如AtomicInteger和ConcurrentHashMap,提升了并发性能。尽管CAS具有高性能、无死锁等优点,但也存在ABA问题、循环开销大及仅支持单变量原子操作等缺点。合理使用CAS,结合实际场景选择同步机制,能有效提升程序性能。
|
7月前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
563 100
|
6月前
|
存储 安全 Java
《数据之美》:Java集合框架全景解析
Java集合框架是数据管理的核心工具,涵盖List、Set、Map等体系,提供丰富接口与实现类,支持高效的数据操作与算法处理。
|
7月前
|
Java 开发者
Java 函数式编程全解析:静态方法引用、实例方法引用、特定类型方法引用与构造器引用实战教程
本文介绍Java 8函数式编程中的四种方法引用:静态、实例、特定类型及构造器引用,通过简洁示例演示其用法,帮助开发者提升代码可读性与简洁性。
|
6月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
7月前
|
安全 Java API
Java SE 与 Java EE 区别解析及应用场景对比
在Java编程世界中,Java SE(Java Standard Edition)和Java EE(Java Enterprise Edition)是两个重要的平台版本,它们各自有着独特的定位和应用场景。理解它们之间的差异,对于开发者选择合适的技术栈进行项目开发至关重要。
1249 1
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
1249 29
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
516 4
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

推荐镜像

更多
  • DNS
  • 下一篇
    开通oss服务