请选择 进入手机版 | 继续访问电脑版
本站特色:极好的技术研究氛围!所有技术交流,必有回复!

疯狂Java联盟

 找回密码
 加入联盟
查看: 188|回复: 1

TreeSet定制排序

[复制链接]
发表于 2018-5-12 17:51:59 | 显示全部楼层 |阅读模式
  1. public class TreeSetTest4 {
  2.     public static void main(String[] args) {
  3.         //TreeSet ts2=new TreeSet();
  4.         TreeSet ts = new TreeSet((o1, o2) -> {
  5.             M m1 = (M) o1;
  6.             M m2 = (M) o2;
  7.             return m1.age > m2.age ? -1 : m1.age < m2.age ? 1 : 0;
  8.         });
  9.         ts.add(new M(5));
  10.         ts.add(new M(8));
  11.         ts.add(new M(-1));
  12.         ts.add(new M(3));
  13.         ts.add(new M(9));
  14.         System.out.println(ts);
  15.         System.out.println(ts.headSet(new M(4)));
  16.     }
  17. }
复制代码
这段代码中Lamdba表达式部分我已经明白了,但是我想不通add新的元素时怎么就和构造器扯上关系了?我查看了TreeSet这里的构造器是:
  1. public TreeSet(Comparator<? super E> comparator) {
  2.         this(new TreeMap<>(comparator));
  3. }
复制代码
这里TreeMap的构造器是;可以看出最终Lamdba表达式的comparator还是被内含在了ts中,但关键是我搞不明白add(new M(5))这个怎么就把这个参数传到comparator中了呢?而且有意思的是,我调试时发现add(new M(5))时,o1,o2居然都是5?这是怎么回事?(PS:这什么破编辑框,在代码框的上面修改,要再想会到代码框下面写就回不去了)
  1. public TreeMap(Comparator<? super K> comparator) {
  2.         this.comparator = comparator;
复制代码

发表于 2018-5-12 18:25:46 | 显示全部楼层
你的理解是对的,当程序创建TreeSet时,如果你传入一个Comparator(就是那个Lambda表达式)作为参数,这个Comparator对象就被内含在TreeSet中了。

问题是:当你每次调用TreeSet的add方法来添加对象时——这个add方法是TreeSet本身代码所实现的,这个add方法需要确定你新增的元素应该添加为哪个节点的子节点(TreeSet底层是红黑树实现的,看源代码会非常清楚),那TreeSet为了确定你新增元素的添加位置,就会去调用它内含的Comparator来比较元素的大小——会用你新增的元素和你TreeSet中部分元素(通常不需要比较全部)比较大小。

实际上,你要了解TreeSet底层的实现机制,其实就是一个红黑树的典型实现。我有一本《疯狂java程序员的基本修养》有关于TreeSet的源代码的解析,你看哪本书会更清楚。
大部分普通开发人员,都只知道TreeSet有哪些特征,这些特征有什么优势,在什么场景下使用。
您需要登录后才可以回帖 登录 | 加入联盟

本版积分规则

小黑屋|手机版|Archiver|疯狂Java联盟 ( 粤ICP备11094030号 )

GMT+8, 2018-10-21 22:14 , Processed in 0.332959 second(s), 6 queries , File On.

快速回复 返回顶部 返回列表