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);
            }
         */
    }
}
相关推荐
twj_one11 小时前
Arthas使用
java
lizz3112 小时前
C++模板编程:从入门到精通
java·开发语言·c++
shoubepatien12 小时前
JAVA -- 05
java·开发语言
寰天柚子12 小时前
Java并发编程中的线程安全问题与解决方案全解析
java·开发语言·python
沐知全栈开发13 小时前
Bootstrap 下拉菜单:设计与实现指南
开发语言
memgLIFE13 小时前
Springboot 分层结构
java·spring boot·spring
shoubepatien13 小时前
JAVA -- 08
java·后端·intellij-idea
kong790692813 小时前
Java新特性-(二)Java基础语法
java·新特性·java 基础语法
yangminlei13 小时前
springboot pom.xml配置文件详细解析
java·spring boot·后端
Evand J13 小时前
【MATLAB例程】多锚点RSSI定位和基站选择方法,基于GDOP、基站距离等因素。以Wi-Fi定位为例,附下载链接
开发语言·matlab·定位·gdop·rssi