声明,本文用得是jdk1.8
前面章节回顾:html
本篇主要讲解TreeMap~java
看这篇文章以前最好是有点数据结构的基础:c#
固然了,若是讲得有错的地方还请你们多多包涵并不吝在评论去指正~微信
按照惯例,我简单翻译了一下顶部的注释(我英文水平渣,若是有错的地方请多多包涵~欢迎在评论区下指正)数据结构
接着咱们来看看类继承图:post
在注释中提到的要点,我来总结一下:this
对我而言,Comparator和Comparable我都忘得差很少了~~~下面就开始看TreeMap的源码来看看它是怎么实现的,而且回顾一下Comparator和Comparable的用法吧!spa
TreeMap的构造方法有4个:.net
能够发现,TreeMap的构造方法大多数与comparator有关:翻译
也就是顶部注释说的:TreeMap有序是经过Comparator来进行比较的,若是comparator为null,那么就使用天然顺序~
打个比方:
TreeMap<Integer, Integer> treeMap = new TreeMap<>(); treeMap.put(1, 5); treeMap.put(2, 4); treeMap.put(3, 3); treeMap.put(4, 2); treeMap.put(5, 1); for (Entry<Integer, Integer> entry : treeMap.entrySet()) { String s = entry.getKey() +"关注公众号:Java3y---->" + entry.getValue(); System.out.println(s); }
咱们来看看TreeMap的核心put方法,阅读它就能够获取很多关于TreeMap特性的东西了~
下面是compare(Object k1, Object k2)
方法
/** * Compares two keys using the correct comparison method for this TreeMap. */ @SuppressWarnings("unchecked") final int compare(Object k1, Object k2) { return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2) : comparator.compare((K)k1, (K)k2); }
若是咱们设置key为null,会抛出异常的,就不执行下面的代码了。
接下来咱们来看看get方法的实现:
点进去getEntry()
看看实现:
若是Comparator不为null,接下来咱们进去看看getEntryUsingComparator(Object key)
,是怎么实现的
删除节点的时候调用的是deleteEntry(Entry<K,V> p)
方法,这个方法主要是删除节点而且平衡红黑树
平衡红黑树的代码是比较复杂的,我就不说了,大家去看吧(反正我看不懂)....
在看源码的时候可能不知道哪一个是核心的遍历方法,由于Iterator有很是很是多~
此时,咱们只须要debug一下看看,跟下去就好!
因而乎,咱们能够找到:TreeMap遍历是使用EntryIterator这个内部类的
首先来看看EntryIterator的类结构图吧:
能够发现,EntryIterator大多的实现都是在父类中:
那接下来咱们去看看PrivateEntryIterator比较重要的方法:
咱们进去successor(e)
方法看看实现:
successor 其实就是一个结点的 下一个结点,所谓 下一个,是按次序排序后的下一个结点。从代码中能够看出,若是右子树不为空,就返回右子树中最小结点。若是右子树为空,就要向上回溯了。在这种状况下,t 是以其为根的树的最后一个结点。若是它是其父结点的左孩子,那么父结点就是它的下一个结点,不然,t 就是以其父结点为根的树的最后一个结点,须要再次向上回溯。一直到 ch 是 p 的左孩子为止。
来源:https://blog.csdn.net/on_1y/article/details/27231855
TreeMap底层是红黑树,可以实现该Map集合有序~
若是在构造方法中传递了Comparator对象,那么就会以Comparator对象的方法进行比较。不然,则使用Comparable的compareTo(T o)
方法来比较。
compareTo(T o)
方法来比较,key必定是不能为null,而且得实现了Comparable接口的。compareTo(T o)
方法来比较,key也是不能为null的public static void main(String[] args) { TreeMap<Student, String> map = new TreeMap<Student, String>((o1, o2) -> { //主要条件 int num = o1.getAge() - o2.getAge(); //次要条件 int num2 = num == 0 ? o1.getName().compareTo(o2.getName()) : num; return num2; }); //建立学生对象 Student s1 = new Student("潘安", 30); Student s2 = new Student("柳下惠", 35); //添加元素进集合 map.put(s1, "宋朝"); map.put(s2, "元朝"); map.put(null, "汉朝"); //获取key集合 Set<Student> set = map.keySet(); //遍历key集合 for (Student student : set) { String value = map.get(student); System.out.println(student + "---------" + value); } }
咱们从源码中的不少地方中发现:Comparator和Comparable出现的频率是很高的,由于TreeMap实现有序要么就是外界传递进来Comparator对象,要么就使用默认key的Comparable接口(实现天然排序)
最后我就来总结一下TreeMap要点吧:
参考资料:
明天要是无心外的话,可能会写ConcurrentHashMap集合,敬请期待哦~~~~
文章的目录导航:https://zhongfucheng.bitcron.com/post/shou-ji/wen-zhang-dao-hang
若是文章有错的地方欢迎指正,你们互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同窗,能够 关注微信公众号:Java3y。为了你们方便,刚新建了一下 qq群:742919422,你们也能够去交流交流。谢谢支持了!但愿能多介绍给其余有须要的朋友