1、TreeMap源码

  1、属性部分:  

  1. private final Comparator<? super K> comparator;//比较器
  2.  
  3. private transient Entry<K,V> root;//根节点
  4.  
  5. private transient int size = 0;//大小
  6.  
  7. private transient int modCount = 0;//结构修改次数
  8.  
  9. 定义一个静态内部对象用以存储:
  10. static final class Entry<K,V> implements Map.Entry<K,V> {
  11. K key;
  12. V value;
  13. Entry<K,V> left;
  14. Entry<K,V> right;
  15. Entry<K,V> parent;
  16. boolean color = BLACK;
  17. ...
  18. 重写了equalshashCodetoString方法等

  2、构造器部分:

  1. public TreeMap() {//无参构造
  2. comparator = null;
  3. }
  4.  
  5. public TreeMap(Comparator<? super K> comparator) {//带比较器构造
  6. this.comparator = comparator;
  7. }
  8.  
  9. public TreeMap(Map<? extends K, ? extends V> m)
  10. public TreeMap(SortedMap<K, ? extends V> m)

  3、put方法:

  1. public V put(K key, V value) {
  2. Entry<K,V> t = root;
  3. //如果根节点为空,设置该元素为根节点;
  4. if (t == null) {
  5. compare(key, key); // type (and possibly null) check
  6.  
  7. root = new Entry<>(key, value, null);
  8. size = 1;
  9. modCount++;
  10. return null;
  11. }
  12. int cmp;
  13. Entry<K,V> parent;
  14. // split comparator and comparable paths
  15. Comparator<? super K> cpr = comparator;//comparator来自哪?构造器中;
  16. //如果传入对象自带比较器:
  17. if (cpr != null) {
  18. do {
  19. parent = t;
  20. cmp = cpr.compare(key, t.key);
  21. if (cmp < 0)
  22. t = t.left;
  23. else if (cmp > 0)
  24. t = t.right;
  25. else
  26. return t.setValue(value);
  27. } while (t != null);
  28. }
  29. //无自带比较器,使用默认的比较机制:
  30. else {
  31. if (key == null)
  32. throw new NullPointerException();
  33. @SuppressWarnings("unchecked")
  34. Comparable<? super K> k = (Comparable<? super K>) key;
  35. do {
  36. parent = t;
  37. cmp = k.compareTo(t.key);//注意key是实现比较器的对象
  38. if (cmp < 0)
  39. t = t.left;
  40. else if (cmp > 0)
  41. t = t.right;
  42. else
  43. return t.setValue(value);
  44. } while (t != null);
  45. }
  46. Entry<K,V> e = new Entry<>(key, value, parent);
  47. if (cmp < 0)
  48. parent.left = e;
  49. else
  50. parent.right = e;
  51. fixAfterInsertion(e);
  52. size++;
  53. modCount++;
  54. return null;
  55. }

  注意:

  <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)。

实例:

  

  1. public class C1 implements Comparable {
  2. String attr1="attr";
  3. static int attr2=2;//注意static
  4. public C1(String attr1,int attr2){
  5. this.attr1=attr1;
  6. this.attr2=attr2;
  7. }
  8. public String getAttr1() {
  9. return attr1;
  10. }
  11. public void setAttr1(String attr1) {
  12. this.attr1 = attr1;
  13. }
  14. public int getAttr2() {
  15. return attr2;
  16. }
  17. public void setAttr2(int attr2) {
  18. this.attr2 = attr2;
  19. }
  20.  
  21. @Override
  22. public int compareTo(Object that) {
  23. // return ((C1)that).attr2-((C1)this).getAttr2();
  24. return 0;
  25. }
  26. public String toString(){return "attr1="+attr1+",attr2="+attr2+";";}
  27. public boolean equals(Object that){
  28. return attr1==((C1)that).getAttr1();
  29. }
  30. public int hashCode(){return attr2;}
  31.  
  32. public static void main(String[] args) {
  33. Set set=new TreeSet();
  34.  
  35. C1 c1=new C1("sttr",4);
  36. set.add(c1);
  37.  
  38. C1 c2=new C1("sttr",5);
  39. set.add(c2);
  40.  
  41. set.add(new C1("sttr",5));
  42.  
  43. set.add(new C1("sttr",3));
  44. set.add(new C1("sttr2",2));
  45.  
  46. System.out.println(set);
  47. }
  48. }
  1. [attr1=sttr,attr2=2;]
  2. //为什么是2?注意attr2是static的,最后一个new C1(..)会改变该所有对象的attr2值。TreeSet没有不会更新Key(就是这个对象new C1(..))

结果1

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

结果2

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

结果3

  1. //compareTo第一行,attr2带static
  2.  
  3. [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. java-poi 批量导入excel数据

    1,首先,前端发送MultipartFile类型文件,后端接收 2,分别创建多个ImportParams对象(easypoi),对应工作蒲 注意:pom中 要有相对应的配置 <!-- easyp ...

  2. java宝典笔记(一)

    第四章java基础知识 4.1基本概念 一.java优点 1.面向对象(封装.继承.多态) 2.可移植性.平台无关,一次编译,到处运行.Windows,Linux,macos等.java为解释性语言, ...

  3. 思科VTP协议(后面有配置案例)

    一.VTP相关理论介绍 1.1 VTP(VLAN trunking protocol)协议是用来在整个交换网络中分发和同步VLAN数据库的,是一个二层协议,思科私有协议. 1.2 VTP域是由一台或者 ...

  4. mysql安装后,过一段时间,在命令行无法启动

    这种问题主要是MYsql没有启动起来,可以在启动管理中开启mysql此服务即可解决

  5. Golang 包管理机制

    Golang 包管理机制 1. 历史 在go1.11之前, 并没有官方的包管理机制(Godep算个半官方), 主流的包管理机制有: GoVendor Glide Godep 在go1.11之后, 官方 ...

  6. 什么是闭包?(python)

    闭包,又称闭包函数或闭合函数,和嵌套函数类似.不同之处在于,闭包函数的外部函数返回的不是一个具体的值,而是一个函数.一般情况下,返回的函数会赋值给一个变量,便于反复调用. def outer(out) ...

  7. C#内联函数 特性 MethodImplOptions.AggressiveInlining)

    [MethodImpl(MethodImplOptions.AggressiveInlining)] 内联函数 Impl:implement的缩写 内联函数 在计算机科学中,内联函数(有时称作在线函数 ...

  8. 【C# 线程】内存模型(C#)---非常重要 【多线程、并发、异步的基础知识】

    内存模型概述 MSDN:理论与实践中的 C# 内存模型 MSDN:理论与实践中的 C# 内存模型,第 2 部分 内存模型就是内存一致性模型. 以下内如来自维基百科 内存一致性模型列表 线性一致性(Li ...

  9. yum报错 , yum相关配置信息,yum重装

    docker源的问题 yum有很多错,比如网络问题,dns问题,timeout 错,还有不知道什么错误 网上有很多,网络问题,dns问题,但是我ping www.baidu.com通,所以不是这个问题 ...

  10. Python:GUI库tkinter(二)

    学习自: Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) - 洪卫 - 博客园 Tkinter简明教程 - 知乎 TkDocs_官方文档 一个Tkinter库较为全面的总结,很 ...