Java集合框架:TreeMap
欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。
欢迎跳转到本文的原文链接:https://honeypps.com/java/java-collection-treemap/
TreeMap定义
package java.util;
public class TreeMap<K,V>extends AbstractMap<K,V>implements NavigableMap<K,V>, Cloneable, java.io.Serializable{
}
public interface NavigableMap<K,V> extends SortedMap<K,V>{}
TreeMap继承AbstractMap,实现NavigableMap、Cloneable、Serializable三个接口。其中AbstractMap表明TreeMap为一个Map即支持key-value的集合, NavigableMap则意味着它支持一系列的导航方法,具备针对给定搜索目标返回最接近匹配项的导航方法 。
TreeMap中同时也包含了如下几个重要的属性:
//比较器,因为TreeMap是有序的,通过comparator接口我们可以对TreeMap的内部排序进行精密的控制
private final Comparator<? super K> comparator;
//TreeMap红-黑节点,为TreeMap的内部类
private transient Entry<K,V> root = null;
//容器大小
private transient int size = 0;
//TreeMap修改次数
private transient int modCount = 0;
//红黑树的节点颜色–红色
private static final boolean RED = false;
//红黑树的节点颜色–黑色
private static final boolean BLACK = true;
对于实体节点Entry是TreeMap的内部类,它有几个重要的属性:
//键
K key;
//值
V value;
//左孩子
Entry<K,V> left = null;
//右孩子
Entry<K,V> right = null;
//父亲
Entry<K,V> parent;
//颜色
boolean color = BLACK;
关于红黑树的实现可以搜索一些相关资料,我觉得参考资料3就不错,博主就不赘述了。
TreeMap特点
- TreeMap是非线程安全的。
可以采用这种方式将TreeMap设置为同步的:Map m = Collections.synchronizedSortedMap(new TreeMap(…)); - TreeMap是用键来进行升序顺序来排序的。通过Comparable 或 Comparator来排序。
TreeMap是SortedMap接口的基于红黑树的实现。此类保证了映射按照升序顺序排列关键字, 根据使用的构造方法不同,可能会按照键的类的自然顺序进行排序,或者按照创建时所提供的比较器(自定义)进行排序。
先举个案例说明一下:
Map<Integer,Integer> map = new TreeMap<>();map.put(1, null);map.put(10, 1);map.put(3, 2);map.put(2, 3);
// map.put(null, 3);for(Entry<Integer, Integer> entry:map.entrySet()){System.out.println(entry.getKey()+":"+entry.getValue());}
输出结果:
1:null
2:3
3:2
10:1
也可以采用自定义的类,引用《Comparable与Comparator浅析》中的Person1举例:
public class Person1 implements Comparable<Person1>
{private int age;private String name;public Person1(String name, int age){this.name = name;this.age = age;}@Overridepublic int compareTo(Person1 o){return this.age-o.age;}@Override public String toString(){return name+":"+age;}
}
测试代码:
Map<Person1,Integer> map = new TreeMap<>();Person1 person1 = new Person1("zzh",18);Person1 person2 = new Person1("jj",17);Person1 person3 = new Person1("qq",19);map.put(person1, 1);map.put(person2, 2);map.put(person3, 3);for(Entry<Person1, Integer> entry:map.entrySet()){System.out.println(entry.getKey()+":"+entry.getValue());}
测试结果:
jj:17:2
zzh:18:1
qq:19:3
只要自定义键的类实现了Comparable接口就可以使用TreeMap的排序功能,也可以通过Comparator接口实现(关于Comparable和Comparator的区别可以翻看《Comparable与Comparator浅析》),如下:
首先引用类Person2:
public final class Person2
{private int age;private String name;public Person2(String name, int age){this.name = name;this.age = age;}@Override public String toString(){return name+":"+age;}//getter and setter方法省略....
}
测试代码:
Map<Person2,Integer> map2 = new TreeMap<>(new Comparator<Person2>(){@Overridepublic int compare(Person2 o1, Person2 o2){if(o1 == null || o2 == null)return 0;return o1.getAge()-o2.getAge();}});Person2 p1 = new Person2("zzh",18);Person2 p2 = new Person2("jj",17);Person2 p3 = new Person2("qq",19);map2.put(p1, 1);map2.put(p2, 2);map2.put(p3, 3);for(Entry<Person2, Integer> entry:map2.entrySet()){System.out.println(entry.getKey()+":"+entry.getValue());}
输出结果:
jj:17:2
zzh:18:1
qq:19:3
可以看到Person2中并没有实现Comparable接口,但是想要和Person1一样能够和TreeMap合作,只需要在创建TreeMap的构造函数中声明一个Comparator接口的实现,譬如上面的例子所示。
3. 由所有此类的“collection 视图方法”所返回的迭代器都是快速失败的。
这点和HashMap一样,所谓快速失败就是在并发集合中,其进行迭代操作时,若有其他线程对其结构性的修改,这是迭代器会立马感知到,并且立刻抛出ConcurrentModificationException异常,而不是等待迭代完成之后才告诉你已经出错。注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。 快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。 因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。
4. 和HashMap一样,如果插入重复的元素,后面的元素会覆盖前面的。
5. 键不可以为null(如果比较器对null做了处理,就可以为null),但是值可以为null。
如上面的案例中,加入:
Person2 p4 = new Person2(null,19);map2.put(p4, 4);
在打印map2的时候就不会报错。
6. TreeMap对containsKey、get、put 和 remove 操作提供了保证的 log(n) 时间开销。
TreeMap提供了很多方法方便大小使用,譬如containsKey, get, put,remove,entrySet等Map通用的方法,也包括fisrtEntry, firstKey, cellingKey, lowerKey等方法,由于篇幅较大,不便赘述,使用前最好翻看一下API或者源码熟悉一下。
HashMap与TreeMap的区别
- 实现方式
HashMap:基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()[可以重写hashCode()和equals()],为了优化HashMap空间的使用,您可以调优初始容量和负载因子。
(1)HashMap(): 构建一个空的哈希映像
(2)HashMap(Map m): 构建一个哈希映像,并且添加映像m的所有映射
(3)HashMap(int initialCapacity): 构建一个拥有特定容量的空的哈希映像
(4)HashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的哈希映像
TreeMap:基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。
(1)TreeMap():构建一个空的映像树
(2)TreeMap(Map m): 构建一个映像树,并且添加映像m中所有元素
(3)TreeMap(Comparator c): 构建一个映像树,并且使用特定的比较器对关键字进行排序
(4)TreeMap(SortedMap s): 构建一个映像树,添加映像树s中所有映射,并且使用与有序映像s相同的比较器排序 - 用途
HashMap:适用于在Map中插入、删除和定位元素。
TreeMap:适用于按自然顺序或自定义顺序遍历键(key)。
HashMap通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap.
参考资料
- 《Comparable与Comparator浅析》
- 《Java中HashMap和TreeMap的区别深入理解》
- 《Java提高篇(二七)-----TreeMap》
欢迎跳转到本文的原文链接:https://honeypps.com/java/java-collection-treemap/
欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。
Java集合框架:TreeMap相关推荐
- Java集合框架综述,这篇让你吃透!
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:平凡希 cnblogs.com/xiaoxi/p/60899 ...
- Java集合框架的知识总结(1)
Java集合框架的知识总结(1) 所有集合类都位于java.util包下.集合中只能保存对象(保存对象的引用变量). Java的集合类主要由两个接口派生而出:Collection和Map,Collec ...
- java集合框架史上最详解(list set 以及map)
title: Java集合框架史上最详解(list set 以及map) tags: 集合框架 list set map 文章目录 一.集合框架总体架构 1.1 集合框架在被设计时需满足的目标 1.2 ...
- 【Java集合源码剖析】Java集合框架
2019独角兽企业重金招聘Python工程师标准>>> Java集合工具包位于Java.util包下,包含了很多常用的数据结构,如数组.链表.栈.队列.集合.哈希表等.学习Java集 ...
- java集合框架综述
一.集合框架图 简化图: 说明:对于以上的框架图有如下几点说明 1.所有集合类都位于java.util包下.Java的集合类主要由两个接口派生而出:Collection和Map,Collection和 ...
- java集合框架容器 java框架层级 继承图结构 集合框架的抽象类 集合框架主要实现类...
本文关键词: java集合框架 框架设计理念 容器 继承层级结构 继承图 集合框架中的抽象类 主要的实现类 实现类特性 集合框架分类 集合框架并发包 并发实现类 什么是容器? 由一个或多个确 ...
- Java集合框架List,Map,Set等全面介绍
Java Collections Framework是Java提供的对集合进行定义,操作,和管理的包含一组接口,类的体系结构. Java集合框架的基本接口/类层次结构: java.util.Colle ...
- java集合框架图(一)
一.集合类简介 Java集合就像一种容器,可以把多个对象(实际上是对象的引用,但习惯上都称对象)"丢进"该容器中.从Java 5 增加了泛型以后,Java集合可以记住容器中对象的数 ...
- java集合框架(Framework)的性能
关于Java集合框架里面常用类的性能测试比较,包括(ArrayList/LinkedList /Vector/Queue/TreeSet/HashSet/LinkedHashSet/TreeMap/H ...
- JAVA集合框架包含的内容
Java集合框架提供了一套性能优良.使用方便的接口和类,他们位于java.util包中. Collection接口 主要有List.Set等实现类,Map接口主要有HashMap.TreeMap等实现 ...
最新文章
- 二叉树:二叉搜索树的创建和插入
- 多场景下的AI疫情防控“天网”:解读云边端联动下的全栈AI技术
- opengl 模板测试 glStencilOp glStencilFunc
- Linux 命令 sudo 用法及配置解析
- 第7章 PCA与梯度上升法
- Core J2EE Patterns - Service Locator--oracle官网
- jquery mobile自定义图标实现方法
- linux 同步IO: sync msync、fsync、fdatasync与 fflush
- centos root密码_如何在CentOS中恢复丢失的root密码
- php手机短信验证码用cookie存好还是session存好,保存登录信息的时候用session好还是cookie好?...
- FFmpeg源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等)
- 网页header 的 meta使用
- HttpClient 该知道一些概念
- 如何搭建一个公司网站?
- 对 kubeadm 进行故障排查
- 常用显卡驱动下载合集
- python+nodejs+php+springboot+vue 社区小区报修 -社区信息管理
- ORBSLAM2单应矩阵计算及代码分析
- win10无法完成更新正在撤销更改怎么办?windows10无法更新正在撤销更改的解决方法
- firefox 下载文件时处理此文件的方法
热门文章
- Nginx教程-http_core_module变量
- oracle与jdbc连接数据库,JDBC与Oracle数据库连接
- 解决MySQL报错... right syntax to use near ‘password ‘XXX‘ at line 1...ERROR 1064 42000: You have an erro
- poj3296--Rinse(三分)
- 关于navicat提权的方法
- HDU 1199 amp;amp; ZOJ 2301 线段树离散化
- 数学分析(Tom M.Apostol) 定理6.7
- 一直无法使用D版的Boson Netsim
- CodeForces - 1267A Apprentice Learning Trajectory(贪心)
- cmi编码用c语言实现,CMI编码与解码