TreeSet与TreeMap的源码分析 JDK7
TreeSet存储原则是:不可重复,有序的。
public TreeSet() {
this(new TreeMap<E,Object>());
}
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
上面是TreeSet常用的两个构造函数。
底层实现也就是TreeMap。
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
/**
* The backing map.
*/
private transient NavigableMap<E,Object> m; // Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
维护了上面两个变量。
add方法
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
因为TreeMap存储的是键值对,因此他将要保存的元素作为key,以一个常量作为值保存到TreeMap中。
这就是为什么TreeSet保存的元素是不可重复的了,因为TreeMap的键不可以重复。
到这里TreeSet也差不多分析完了,主要还是分析TreeMap,因为实现在他里面。
TreeMap常用构造函数:
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
public TreeMap() {
comparator = null;
}
这里Comparator是一个比较器,这就是为什么TreeSet是有序的原因了。
private final Comparator<? super K> comparator;
private transient Entry<K,V> root = null;
上面两个主要变量,一个是比较器,一个是根。这个根是因为数据结构而设计的,一种红黑树或者叫二叉树的一种数据结构。TreeMap也是根据这个数据结构而设计的。
好,我们来看看添加元素的真面目吧。
public V put(K key, V value) {
Entry<K,V> t = root;//得到根节点
if (t == null) {//添加第一个元素
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);//根节点就是第一个添加进来的元素,前一个节点为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);//相等直接返回,且将新的元素值替换掉旧的
} while (t != null);//直到没有左右节点
}
else {
if (key == null)
throw new NullPointerException();
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);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;//此时,parent元素的值最小,新元素的值比parent还小,放在parent左边
else
parent.right = e;//此时,parent元素的值最最大,新元素的值比parent还大,放在parent右边
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
好,现在元素放进去了,要取出来吧。使用iterator()方法。
//TreeSet
public Iterator<E> iterator() {
return m.navigableKeySet().iterator();
}
TreeSet的iterator方法是调用了TreeMap的方法。这个方法是从JDK1.6开始有的
/**
* @since 1.6
*/
public NavigableSet<K> navigableKeySet() {
KeySet<K> nks = navigableKeySet;
return (nks != null) ? nks : (navigableKeySet = new KeySet(this));
}
实际上就是调用了KeySet的iterator方法。
TreeSet与TreeMap的源码分析 JDK7的更多相关文章
- TreeSet实现原理及源码分析
类似于HashMap和HashSet之间的关系,HashSet底层依赖于HashMap实现,TreeSet底层则采用一个NavigableMap来保存TreeSet集合的元素.但实际上,由于Navig ...
- HashMap与TreeMap源码分析
1. 引言 在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...
- Java集合源码分析(六)TreeSet<E>
TreeSet简介 TreeSet 是一个有序的集合,它的作用是提供有序的Set集合.它继承于AbstractSet抽象类,实现了NavigableSet<E>, Cloneable, j ...
- 死磕 java集合之TreeSet源码分析
问题 (1)TreeSet真的是使用TreeMap来存储元素的吗? (2)TreeSet是有序的吗? (3)TreeSet和LinkedHashSet有何不同? 简介 TreeSet底层是采用Tree ...
- 集合之TreeSet(含JDK1.8源码分析)
一.前言 前面分析了Set接口下的hashSet和linkedHashSet,下面接着来看treeSet,treeSet的底层实现是基于treeMap的. 四个关注点在treeSet上的答案 二.tr ...
- Java集合源码分析(十)——TreeSet
简介 TreeSet就是一个集合,里面不能有重复的元素,但是元素是有序的. TreeSet其实就是调用了TreeMap实现的,所以,它也不是线程安全的.可以实现自然排序或者根据传入的Comparato ...
- 【集合框架】JDK1.8源码分析之TreeMap(五)
一.前言 当我们需要把插入的元素进行排序的时候,就是时候考虑TreeMap了,从名字上来看,TreeMap肯定是和树是脱不了干系的,它是一个排序了的Map,下面我们来着重分析其源码,理解其底层如何实现 ...
- TreeMap 源码分析
简介 TreeMap最早出现在JDK 1.2中,是 Java 集合框架中比较重要一个的实现.TreeMap 底层基于红黑树实现,可保证在log(n)时间复杂度内完成 containsKey.get.p ...
- 集合之TreeMap(含JDK1.8源码分析)
一.前言 前面所说的hashMap和linkedHashMap都不具备统计的功能,或者说它们的统计性能的时间复杂度都不是很好,要想对两者进行统计,需要遍历所有的entry,时间复杂度比较高,此时,我们 ...
随机推荐
- 初探中间件(middleware)
初探中间件(middleware) 因为考虑到文章的长度, 所以 BaseHandler 的展开被推迟了. 在 BaseHandler 中隐藏着中间件的信息, 较常见的 SessionMiddlewa ...
- Redis系统学习 二、数据结构
一.字符串 1.在Redis里,字符串是最基本的数据结构.当你在思索着关键字-值对时,你就是在死锁着字符串数据结构.不要被名字给搞混了. 常见实例: set users:leto " ...
- WCF学习笔记之传输安全
WCF学习笔记之传输安全 最近学习[WCF全面解析]下册的知识,针对传输安全的内容做一个简单的记录,这边只是简单的记录一些要点:本文的内容均来自[WCF全面解析]下册: WCF的传输安全主要涉及认证. ...
- offsetWidth, offsetHeight, offsetLeft, offsetTop,clientWidth, clientHeight,clientX,pageX,screenX
offsetWidth: 元素在水平方向上占用的空间大小.包括元素的宽度,内边距,(可见的)垂直滚动条的宽度,左右边框的宽度. offsetHeight:元素在垂直方向上占用的空间大小,包括元素的高度 ...
- JBoss + EJB3 + MySql : 开发第一个EJB
JBoss开发Bean并不困难,而对于不知道的人来说,数据库配置才是比较棘手的问题.现在我们就来一步一步开发一个EJB3 + MySql的Bean. 一.MySql数据库的配置 1. 配置数据源 在 ...
- Android本地化资源目录详解
我们可以设想,有两个不同分辨率的手机(320*480和480*800)要使用一些图像资源,为了使图像不失真,就需要为不同分辨率的手机指定不同的图像,为此就需要建立不同的资源目录. 在res目录中建立了 ...
- HTTP协议系列(2)--顺带离职的一些想法
一.聊聊离职感悟 来杭州也是将近3个月了,也迎来我的第一次辞职,有可能你会说我傻怎么不拿年终奖,也有可能你会不理解为什么3个月就要辞职:我只能说我是怀揣的梦想来的,我想着进一步的提升,想着成 ...
- AngularJS2之Angular正式初探
前言:angular的官方教程真的不错.强烈推荐!!!] 按照环境搭建教程新建一个项目: 项目的结构如下: 其中package.json指示node需要安装的插件(npm install指令会安装的插 ...
- PostgreSQL学习手册(常用数据类型)
一.数值类型: 下面是PostgreSQL所支持的数值类型的列表和简单说明: 名字 存储空间 描述 范围 smallint 2 字节 小范围整数 -32768 到 +32767 integer ...
- 关于intelliJ idea创建servlet提示cannot resolve symbol‘servlet’的问题
在刚刚折腾idea的时候会出现一系列的问题,就比如创建Servlet的时候,编辑器提示cannot resolve symbol'servlet'.出现这样的问题是因为在第一次用idea的时候还没有配 ...