1、TreeMap源码

  1、属性部分:  

 private final Comparator<? super K> comparator;//比较器

 private transient Entry<K,V> root;//根节点

private transient int size = 0;//大小

private transient int modCount = 0;//结构修改次数

定义一个静态内部对象用以存储:
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;
...
重写了equals、hashCode、toString方法等

  2、构造器部分:

 public TreeMap() {//无参构造
comparator = null;
} public TreeMap(Comparator<? super K> comparator) {//带比较器构造
this.comparator = comparator;
} public TreeMap(Map<? extends K, ? extends V> m)
public TreeMap(SortedMap<K, ? extends V> m)

  3、put方法:

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);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;//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();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);//注意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;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}

  注意:

  <1>:首先,如果想往TreeMap中存放Entry<K,V>,那么其K必须是实现compareTo方法的,那么K所对应的类需要implements comparable接口。当然常用类中已经重写了这个方法,所以我们可以直接使用:TreeMap.put(int a,String b)等;

  <2>:TreeMap是基于红黑树的数据结构,TreeMap中判断新入元素的存储位置时,只需要通过compareTo方法判断两个对象的Key是否相同:相同,则更新Value,返回旧值Value;不同,则插在左或右子节点上,不同于HashMap通过Key的hashCode判断存储位置,所以即使在TreeMap中没有hashCode和equals方法的重写,对于put也没有影响。

  <3>:put入新节点后,TreeMap需要调整整个红黑树的结构。后续学习......;

2、TreeSet的add源码

   public boolean add(E e) { return m.put(e, PRESENT)==null; }

  看到add只需要接收一个参数e,m是一个 private transient NavigableMap<E,Object> m; ,接口,其实现类是TreeMap,因此知道,TreeSet的add通过调用TreeMap的put方法实现添加节点操作,但是由于add只接收一个形参e,故TreeSet生成了一个PRESENT以构成<K,V>的形式,PRESENT是 private static final Object PRESENT = new Object(); 完全是用来凑得嘛。

  但是一定要注意:TreeMap的put中当通过comparedTo判断两个节点的Key相等时,会更新Value。而TreeSet的Value并没有什么作用,故可Key还是原来的Key,并没有发生改变。

总结:如果要插入新元素到TreeMap或TreeSet中:

  1、TreeMap中若newKey.compareTo(oldkey)返回值是0,那么Key不变,更新Value的值为newValue,返回oldValue。

  2、TreeSet中,简单可以理解为不更新(因为我们只用Key)。

实例:

  

public class C1 implements Comparable {
String attr1="attr";
static int attr2=2;//注意static
public C1(String attr1,int attr2){
this.attr1=attr1;
this.attr2=attr2;
}
public String getAttr1() {
return attr1;
}
public void setAttr1(String attr1) {
this.attr1 = attr1;
}
public int getAttr2() {
return attr2;
}
public void setAttr2(int attr2) {
this.attr2 = attr2;
} @Override
public int compareTo(Object that) {
// return ((C1)that).attr2-((C1)this).getAttr2();
return 0;
}
public String toString(){return "attr1="+attr1+",attr2="+attr2+";";}
public boolean equals(Object that){
return attr1==((C1)that).getAttr1();
}
public int hashCode(){return attr2;} public static void main(String[] args) {
Set set=new TreeSet(); C1 c1=new C1("sttr",4);
set.add(c1); C1 c2=new C1("sttr",5);
set.add(c2); set.add(new C1("sttr",5)); set.add(new C1("sttr",3));
set.add(new C1("sttr2",2)); System.out.println(set);
}
}
[attr1=sttr,attr2=2;]
//为什么是2?注意attr2是static的,最后一个new C1(..)会改变该所有对象的attr2值。TreeSet没有不会更新Key(就是这个对象new C1(..))

结果1

[attr1=sttr,attr2=4;]
//正常,没有更新

结果2

//compareTo第一行,attr2不带static
[attr1=sttr,attr2=5;, attr1=sttr,attr2=4;, attr1=sttr,attr2=3;, attr1=sttr2,attr2=2;]

结果3

//compareTo第一行,attr2带static

[attr1=sttr,attr2=2;]

结果4

TreeMap与TreeSet的源码分析的更多相关文章

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

    转载 Java 集合系列12之 TreeMap详细介绍(源码解析)和使用示例 一.TreeMap 简单介绍 什么是Map? 在数组中我们通过数组下标来对数组内容进行索引的,而在Map中我们通过对象来对 ...

  2. TreeMap实现原理及源码分析

    TreeMap是一个有序的key-value集合,基于红黑树(Red-Black tree)实现.该映射根据其键的自然顺序进行排序,或者根据创建时提供的Comparator进行排序. 对于TreeMa ...

  3. Java集合源码分析(六)TreeSet<E>

    TreeSet简介 TreeSet 是一个有序的集合,它的作用是提供有序的Set集合.它继承于AbstractSet抽象类,实现了NavigableSet<E>, Cloneable, j ...

  4. 死磕 java集合之TreeSet源码分析

    问题 (1)TreeSet真的是使用TreeMap来存储元素的吗? (2)TreeSet是有序的吗? (3)TreeSet和LinkedHashSet有何不同? 简介 TreeSet底层是采用Tree ...

  5. 集合之TreeSet(含JDK1.8源码分析)

    一.前言 前面分析了Set接口下的hashSet和linkedHashSet,下面接着来看treeSet,treeSet的底层实现是基于treeMap的. 四个关注点在treeSet上的答案 二.tr ...

  6. Java集合源码分析(十)——TreeSet

    简介 TreeSet就是一个集合,里面不能有重复的元素,但是元素是有序的. TreeSet其实就是调用了TreeMap实现的,所以,它也不是线程安全的.可以实现自然排序或者根据传入的Comparato ...

  7. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  8. 【集合框架】JDK1.8源码分析之TreeMap(五)

    一.前言 当我们需要把插入的元素进行排序的时候,就是时候考虑TreeMap了,从名字上来看,TreeMap肯定是和树是脱不了干系的,它是一个排序了的Map,下面我们来着重分析其源码,理解其底层如何实现 ...

  9. TreeMap 源码分析

    简介 TreeMap最早出现在JDK 1.2中,是 Java 集合框架中比较重要一个的实现.TreeMap 底层基于红黑树实现,可保证在log(n)时间复杂度内完成 containsKey.get.p ...

随机推荐

  1. VS2019配置eigen

    本文讲述如何在VS2019中配置eigen eigen版本:eigen-3.3.9 百度网盘地址:https://pan.baidu.com/s/1Bu5A58qV2n8doDs4NpPfJQ  提取 ...

  2. [LeetCode]1365. 有多少小于当前数字的数字

    给你一个数组 nums,对于其中每个元素 nums[i],请你统计数组中比它小的所有数字的数目. 换而言之,对于每个 nums[i] 你必须计算出有效的 j 的数量,其中 j 满足 j != i 且 ...

  3. 解决:阿里云服务器被植入挖矿程序后修改密码失败的问题(报错:passwd: Authentication token manipulation error)

    如下图,在修改密码的时候会报错 原因: 通常不能修改密码都是/etc/passwd文件或者/etc/shadow文件被锁住了 解决: 检查/etc/passwd文件和/etc/shadow文件是否被锁 ...

  4. [题解]UVA10269 Adventure of Super Mario

    链接:http://vjudge.net/problem/viewProblem.action?id=24902 描述:由城镇.村子和双向边组成的图,从A+B走到1,要求最短路.有K次瞬移的机会,距离 ...

  5. 基于隐私保护技术的DNS通信协议介绍

    本文提出了一种基于用户数据报协议的DNS传输中用户隐私保护的加密方法:DNSDEA.该方法采用PKI加密体系与DNS协议相融合,不仅解决了域名隐私保护问题,而且与传统DNS体系相兼容,保持了DNS系统 ...

  6. Win10搭建web服务实现文件共享

    配置Internet Information Services服务,实现文件共享. 1.打开控制面板,启用IIS服务. 启用IIS服务,系统会自动搜索并安装IIS服务. 2.管理web服务 此时在浏览 ...

  7. 【C# 线程】优先级反转与优先级继承

    什么是优先级反转(翻转)优先级反转,是指在使用信号量时,可能会出现的这样一种不合理的现象,即:    高优先级任务被低优先级任务阻塞,导致高优先级任务迟迟得不到调度.但其他中等优先级的任务却能抢到CP ...

  8. SyntaxError: keyword can't be an expression

    创建字典对象时: D1=dict('name'='Bob','age'=20,'score'=90) SyntaxError: keyword can't be an expression 解决方法: ...

  9. CPU长指令(VLIW)失败的主要原因是什么,VLIW真的无药可救吗?

    software和hardware之间总是存在tradeoff:要么是hardware结构复杂,software灵活.要么是hardware结构保持简洁清晰,software干一些脏活累活.VLIW就 ...

  10. js识别手机型号做业务判断

    navigator为Window对象的一个属性,指向了一个包含浏览器相关信息的对象. navigatot中包含了一些常用到的属性,如: navigator.appVersion 浏览器的版本号 nav ...