Java_TreeSet与TreeMap源码解读

TreeSet底层是TreeMap,二者区别在于:

java 复制代码
    public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }

TreeSet在使用方法时,e作为元素添加,而PRESENT作为一个用于占位的空对象,表示没有意义

TreeMap使用方法时,由于是作为键值对添加进去的,此时e 就等于key,而PRESENT 就等于value

TreeSet演示:

java 复制代码
package com.CollectionStu_.Set_;

import java.util.Comparator;
import java.util.TreeSet;
@SuppressWarnings({"all"})
public class TreeSet_ {
    public static void main(String[] args) {
//        TreeSet treeSet = new TreeSet();
        //1.当我们使用无参构造器创建TreeSet时,仍然是无序的
        //2.可以使用TreeSet提供的一个构造器,可以传入一个比较器(匿名内部类)
        //  并指定排序规则
        //例:希望添加的元素能够按照字符串大小进行排序(这里是从小到大)
        TreeSet treeSet = new TreeSet(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                //下面调用String的 compareTo方法进行字符串大小比较
                return ((String)o2).compareTo((String) o1);//从大到小把o2 和o1 对调即可
            }
        });

        //添加数据
        treeSet.add("jack");
        treeSet.add("tom");
        treeSet.add("nihao");
        treeSet.add("mary");

        System.out.println(treeSet);
        //排序前(直接输出):[jack, mary, nihao, tom]
        //排序后(从小到大):[tom, nihao, mary, jack]

        //源码分析:
        /*
        构造器:
        public TreeSet(Comparator<? super E> comparator) {
            this(new TreeMap<>(comparator));
        }
        构造器会把传入的匿名对象new Comparator() 赋给TreeSet底层的TreeMap的属性this.comparator

        在调用add("tom") 时,在底层会执行到
        Comparator<? super K> cpr = comparator; //cpr就是匿名内部类(对象)
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);  //动态绑定到匿名内部类的compare()
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else                            //如果相等,即返回0,这个数据(Key)就没有加入
                    return t.setValue(value);
            } while (t != null);
        }
         */
    }
}

TreeMap演示:

java 复制代码
package com.MapStu_.Map_;

import java.util.Comparator;
import java.util.TreeMap;
@SuppressWarnings({"all"})
public class TreeMap_ {
    public static void main(String[] args) {
        TreeMap treeMap = new TreeMap();
        treeMap.put("jack","杰克");
        treeMap.put("tom","汤姆");
        treeMap.put("nihao","泥嚎");
        treeMap.put("smith","史密斯");
        //使用默认构造器创建TreeMap(无序的,也没有排序)
        System.out.println(treeMap);//{jack=杰克, nihao=泥嚎, smith=史密斯, tom=汤姆}

        //使用带comparator的构造器控制排序
        //    public TreeMap(Comparator<? super K> comparator) {
        //        this.comparator = comparator;
        //    }
        //例:要求按照传入的key(String) 大小进行排序
        TreeMap treeMap1 = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).compareTo((String)o2);
            }
        });
        treeMap1.put("jack","杰克");
        treeMap1.put("tom","汤姆");
        treeMap1.put("nihao","泥嚎");
        treeMap1.put("smith","史密斯");
        System.out.println(treeMap1);

        //要求按照字符串长度大小排序
        TreeMap treeMap2 = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).length() - ((String)o2).length();
            }
        });

            /*

            源码解读:
            1. 构造器. 把传入的实现了 Comparator接口的匿名内部类(对象),传给给TreeMap的comparator
             public TreeMap(Comparator<? super K> comparator) {
                this.comparator = comparator;
            }
            2. 调用put方法
            2.1 第一次添加, 把k-v 封装到 Entry对象,放入root
            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;
            }
            2.2 以后添加
            Comparator<? super K> cpr = comparator;
            if (cpr != null) {
                do { //遍历所有的key , 给当前key找到适当位置
                    parent = t;
                    cmp = cpr.compare(key, t.key);//动态绑定到我们的匿名内部类的compare
                    if (cmp < 0)
                        t = t.left;
                    else if (cmp > 0)
                        t = t.right;
                    else  //如果遍历过程中,发现准备添加Key 和当前已有的Key 相等,就不添加
                        return t.setValue(value);
                } while (t != null);
            }
         */
    }
}
相关推荐
桦说编程1 小时前
从 ForkJoinPool 的 Compensate 看并发框架的线程补偿思想
java·后端·源码阅读
躺平大鹅3 小时前
Java面向对象入门(类与对象,新手秒懂)
java
初次攀爬者4 小时前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺4 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
Derek_Smart5 小时前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot
NE_STOP6 小时前
MyBatis-mybatis入门与增删改查
java
孟陬10 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端
想用offer打牌10 小时前
一站式了解四种限流算法
java·后端·go
华仔啊10 小时前
Java 开发千万别给布尔变量加 is 前缀!很容易背锅
java