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);
            }
         */
    }
}
相关推荐
教练、我想打篮球2 小时前
05 kafka 如何存储较大数据记录
java·kafka·record
uesowys2 小时前
华为OD算法开发指导-简易内存池
java·算法·华为od
gladiator+2 小时前
Java中的设计模式------策略设计模式
java·开发语言·设计模式
Lucifer__hell2 小时前
【python+tkinter】图形界面简易计算器的实现
开发语言·python·tkinter
2301_812914872 小时前
py day34 装饰器
开发语言·python
期待のcode3 小时前
Dockerfile镜像构建
java·docker·容器
小满、3 小时前
对象住哪里?——深入剖析 JVM 内存结构与对象分配机制
java·jvm·#java对象分配·#hotspot实现
卡提西亚3 小时前
C++笔记-24-文件读写操作
开发语言·c++·笔记
How_doyou_do3 小时前
模态框的两种管理思路
java·服务器·前端