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);
            }
         */
    }
}
相关推荐
葡萄成熟时 !9 小时前
黑马学生管理系统
java·开发语言
秋邱9 小时前
高等教育 AI 智能体的 “导学诊践” 闭环
开发语言·网络·数据库·人工智能·python·docker
沐浴露z9 小时前
为什么使用SpringAI时通常用Builder来创建对象?详解 【Builder模式】和【直接 new】的区别
java·python·建造者模式
j***63089 小时前
MacOS升级ruby版本
开发语言·macos·ruby
阿杰真不会敲代码9 小时前
Filter与Interceptor深度解析:分清这两个“拦截器”,面试不再掉坑
java·spring boot·面试
g***86699 小时前
PHP进阶-在Ubuntu上搭建LAMP环境教程
开发语言·ubuntu·php
合作小小程序员小小店9 小时前
桌面开发,拼车管理系统开发,基于C#,winform,sql server数据库
开发语言·数据库·sql·microsoft·c#
带刺的坐椅9 小时前
Solon AI 开发学习6 - chat - 两种 http 流式输入输出
java·ai·solon
客梦9 小时前
Java 道路信息系统
java·笔记