TreeMap源码详解

news/2024/9/29 13:57:01 标签: TreeMap, HashMap, Map, 面试, Java, 职场和发展, 性能优化

优质博文:IT-BLOG-CN

背景:昨天有人问我,他想将Map中的Key按照顺序进行遍历,我说直接使用keySet方法获取到Set集合,因为它是集成Collection接口,所以包含了sort方法后遍历取value值即可。但当看到Map>TreeMap的那一刻,我发现自己错了。

再说一个很重要的概念:
【1】Map>TreeMapkey不能为nullvalue可以为null;
【2】Map>HashMapkey可以为nullvalue可以为null;
【3】ConcurrentMap>HashMapHashTablekeyvalue都不可以为null;

Map>TreeMap__10">一、Map>TreeMap 结构

如类图所示:Map>TreeMap也是一种Map实现了SortedMap<K,V>接口,说明他内部对Key进行了排序。而Map>HashMap内部的Key是无序的。Map>TreeMap的底层是一颗红黑树,这是一种自然平衡二叉搜索树,可以保证在插入,删除,查找等操作中的时间复杂度为O(log n)

使用Map>TreeMap时,放入的Key必须实现Comparable接口。StringInteger这些类已经实现了Comparable接口,因此可以直接作为Key使用。作为Value的对象则没有任何要求。

如果作为Keyclass没有实现Comparable接口,那么,必须在创建Map>TreeMap时同时指定一个自定义排序算法,我们可以先看下Map>TreeMap的构造器:

// 默认构造函数。使用该构造函数,Map>TreeMap中的元素按照自然排序进行排列。
Map>TreeMap()
 
// 创建的Map>TreeMap包含Map
Map>TreeMap(Map<? extends K, ? extends V> copyFrom)
 
// 指定Tree的比较器
Map>TreeMap(Comparator<? super K> comparator)
 
// 创建的TreeSet包含copyFrom
Map>TreeMap(SortedMap<K, ? extends V> copyFrom)

实际开发中案例:Comparator接口要求实现一个比较方法,它负责比较传入的两个元素p1p2,如果p1 < p2,则返回负数,通常是-1,如果p1 == p2,则返回0,如果p1 > p2,则返回正数,通常是1Map>TreeMap内部根据比较结果对Key进行排序。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Map<Person, Integer> map = new Map>TreeMap<>(new Comparator<Person>() {
            public int compare(Person p1, Person p2) {
                return p1.name.compareTo(p2.name);
            }
        });
        map.put(new Person("Tim"), 1);
        map.put(new Person("Baby"), 2);
        map.put(new Person("Luna"), 3);
        for (Person key : map.keySet()) {
            System.out.println(key);
        }
        // {Person: Baby}, {Person: Luna}, {Person: Tim}
        System.out.println(map.get(new Person("Baby"))); // 2
    }
}

class Person {
    public String name;
    Person(String name) {
        this.name = name;
    }
    public String toString() {
        return "{Person: " + name + "}";
    }
}

Person类并未覆写equals()hashCode(),因为Map>TreeMap不使用equals()hashCode()

Map>TreeMap_API_69">二、Map>TreeMap API

基础数据:

// 创建一个 Map>TreeMap
Map>TreeMap<String, Integer> map = new Map>TreeMap<>();

// 向 Map>TreeMap 中添加键值对
map.put("Alice", 90);
map.put("Bob", 80);
map.put("Charlie", 70);
map.put("David", 60);

Map>TreeMap因为排序等特性,所以包含了一些特殊的API这里简单介绍一下:

【1】firstKeylastKey:分别返回Map>TreeMap中最小和最大的键;

// 返回 Map>TreeMap 中最小和最大的键
System.out.println(map.firstKey()); // Alice
System.out.println(map.lastKey()); // David

【2】lowerKeyhigherKey:分别返回Map>TreeMap中小于和大于给定键的最近的键;

// 返回 Map>TreeMap 中小于和大于给定键的最近的键
System.out.println(map.lowerKey("Bob")); // Alice
System.out.println(map.higherKey("Bob")); // Charlie

【3】floorKeyceilingKey:分别返回Map>TreeMap中小于等于和大于等于给定键的最近的键;

// 返回 Map>TreeMap 中小于等于和大于等于给定键的最近的键
System.out.println(map.floorKey("Bob")); // Bob
System.out.println(map.ceilingKey("Bob")); // Bob

【4】subMap:返回一个子映射,包含给定范围内的所有键值对;

// 返回一个子映射,包含给定范围内的所有键值对
System.out.println(map.subMap("Alice", true, "Charlie", true)); // {Alice=90, Bob=80, Charlie=70}

【5】headMaptailMap:分别返回一个子映射,包含小于或等于给定键或大于或等于给定键的所有键值对;

// 返回一个子映射,包含小于或等于给定键或大于或等于给定键的所有键值对
System.out.println(map.headMap("Charlie", true)); // {Alice=90, Bob=80, Charlie=70}
System.out.println(map.tailMap("Charlie", true)); // {Charlie=70, David=60}

【6】firstEntrylastEntry:分别返回Map>TreeMap中最小和最大的键值对;

// 返回 Map>TreeMap 中最小和最大的键值对
System.out.println(map.firstEntry()); // Alice=90
System.out.println(map.lastEntry()); // David=60

【7】lowerEntryhigherEntry:分别返回Map>TreeMap中小于和大于给定键的最近的键值对;

// 返回 Map>TreeMap 中小于和大于给定键的最近的键值对
System.out.println(map.lowerEntry("Bob")); // Alice=90
System.out.println(map.higherEntry("Bob")); // Charlie=70

【8】floorEntryceilingEntry:分别返回Map>TreeMap中小于等于和大于等于给定键的最近的键值对;

// 返回 Map>TreeMap 中小于等于和大于等于给定键的最近的键值对
System.out.println(map.floorEntry("Bob")); // Bob=80
System.out.println(map.ceilingEntry("Bob")); // Bob=80

【9】pollFirstEntrypollLastEntry:分别返回并删除Map>TreeMap中最小和最大的键值对;

// 返回并删除 Map>TreeMap 中最小和最大的键值对
System.out.println(map.pollFirstEntry()); // Alice=90
System.out.println(map.pollLastEntry()); // David=60

根据上述的API可知,如果遇到如下场景时,应当想到使用Map>TreeMap
【1】需要按照键的自然顺序或者指定的比较器进行排序的场景,例如字典,排行榜,日程安排等。
【2】需要快速找到映射中最小或者最大的键或者值的场景,例如优先队列,堆,区间查询等。
【3】需要快速找到映射中某个范围内的所有键或者值的场景,例如范围搜索,前缀匹配,区间统计等。

三、注意事项

【1】如果使用自然顺序进行排序,则需要保证键是可比较的(实现了Comparable接口),否则会抛出ClassCastException异常。
【2】如果使用指定的比较器进行排序,则需要保证比较器是一致的(满足自反性,对称性,传递性),否则可能导致排序结果不正确或者抛出ClassCastException异常。
【3】如果在遍历Map>TreeMap的过程中修改了其结构(添加或删除了元素),则可能导致ConcurrentModificationException异常或者不确定的行为。
【4】如果在遍历Map>TreeMap的过程中修改了其元素(改变了键或者值),则可能导致排序结果不正确或者不确定的行为。
【5】Map>TreeMap不是线程安全的,如果多个线程同时访问或修改Map>TreeMap,则需要进行同步处理。


http://www.niftyadmin.cn/n/5683131.html

相关文章

基于SpringCloud的微服务架构下安全开发运维准则

为什么要进行安全设计 微服务架构进行安全设计的原因主要包括以下几点&#xff1a; 提高数据保护&#xff1a;微服务架构中&#xff0c;服务间通信频繁&#xff0c;涉及到大量敏感数据的交换。安全设计可以确保数据在传输和存储过程中的安全性&#xff0c;防止数据泄露和篡改。…

【流计算】流计算概论

前言 作者在之前写过一个大数据的专栏&#xff0c;包含GFS、BigTable、MapReduce、HDFS、Hadoop、LSM树、HBase、Spark&#xff0c;专栏地址&#xff1a; https://blog.csdn.net/joker_zjn/category_12631789.html?fromshareblogcolumn&sharetypeblogcolumn&sharerI…

linux项目_c语言:Makefile编写、动态库生成、添加动态库路径

一直想搞懂Linux中Makefile是怎么管理项目的&#xff0c;知识积累到一定程度后&#xff0c;我就做了一个自己的缩小项目去把剩下的细节搞清楚 代码&#xff1a; Service.c: #include <stdio.h> #include "lib_sevr.h" int main(){printf("输入a, b的值…

【实战篇】自增主键为什么不是连续的?

背景 由于自增主键可以让主键索引尽量地保持递增顺序插入&#xff0c;避免了页分裂&#xff0c;因此索引更紧凑。 之前我见过有的业务设计依赖于自增主键的连续性&#xff0c;也就是说&#xff0c;这个设计假设自增主键是连续的。但实际上&#xff0c;这样的假设是错的&#…

影刀---实现我的第一个抓取数据的机器人

你们要的csdn自动回复机器人在这里文末哦&#xff01; 这个上传的资源要vip下载&#xff0c;如果想了解影刀这个软件的话可以私聊我&#xff0c;我发你 目录 1.网页对象2.网页元素3.相似元素组4.元素操作设置下拉框复选框滚动条获取元素的信息 5.变量6.数据的表达字符串变量列…

前端开发设计模式——策略模式

目录 一、策略模式的定义和特点 1.定义&#xff1a; 2.特点&#xff1a; 二、策略模式的实现方式 1.定义策略接口&#xff1a; 2.创建具体策略类&#xff1a; 3.定义上下文类&#xff1a; 三、策略模式的应用场景 1.表单验证场景&#xff1a; 2.动画效果切换场景&…

DePIN 代表项目 CESS 受邀出席国会山活动,向议员展示创新 DePIN 技术

我们非常激动地宣布&#xff0c;CESS 已受邀参加由美国区块链协会主办的国会山活动&#xff0c;将于当地时间 2024 年 10 月 2 日向一众国会议员展示创新的 DePIN 技术&#xff01;本次关于去中心化物理基础设施网络&#xff08;DePIN&#xff09;的重要会议中&#xff0c;CESS…

基于SpringBoot+Vue的社区智慧医疗养老系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…