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. 移动BI,移动报表平台

    ​随着大数据时代的到来,随着商业智能衍生出来的移动BI也将处于一片大好的形式中,由于智能手机.移动应用的普及,越来越多的办公软件均已支持了移动办公,这也给移动BI带来了更多的想象,通过一部手机就可以随 ...

  2. BI报表系统该如何集成到其他系统呢?

    近期小麦我经常收到很多用户的反馈,想知道Smartbi的报表能不能从微信/钉钉之类的直接跳转到已做好的报表页面?他们都希望通过这种方式尽可能地避免由于各个管理软件账号密码不同而造成的不便,能够在日常工 ...

  3. C# Semaphore 信号量 锁 简单理解

    信号量(Semaphore) Semaphore 一般译作 信号量,它也是一种线程同步工具,主要用于多个线程对共享资源进行并行操作的一种工具类.它代表了一种许可的概念,是否允许多线程对同一资源进行操作 ...

  4. C#基于Redis实现分布式锁

    [本博客属于原创,如需转载,请注明出处:https://www.cnblogs.com/gdouzz/p/12097968.html] 最近研究库存的相关,在高峰期经常出现超卖等等情况,最后根据采用是 ...

  5. 判断访问类型是pc端还是移动端

    /**      * 判断访问类型是电脑还是手机      */     $(function(){         var mobile_flag = isMobile(); // true为PC端 ...

  6. Qt:QCoreApplication

    0.说明 QCoreApplication提供了有关当前运行程序的相关信息,当前程序应当是非GUI程序.对于GUI程序,应该用QGuiApplication,而对于采用了Qt Widget模块的程序, ...

  7. k8s-coredns 介绍和部署

    1.k8s-coredns 实现了集群内部通过服务名进行可以访问.添加服务后,会自动添加一条解析记录 cat /etc/resolv.conf nameserver 10.0.0.2 search k ...

  8. js 数组/对象/日期的浅克隆

    //封装 function clone (obj) { // Handle the 3 simple types, and null or undefined if (null == obj || & ...

  9. 递归——深度优先搜索(DFS)——以滑雪问题为例(自顶而下)

    一.问题:滑雪 问题描述:小明喜欢滑雪,为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.小明想知道在一个区域中最长底滑坡.区域由一个二维数组给出.数组的每 ...

  10. Triple Shift

    来源:Atcoder ARC 136 B - Triple Shift (atcoder.jp) 题解:这道题我们不可能去硬模拟(大多数这种题都不能这样去模拟的),然后我们就要去发现特性, 发现把 a ...