集合源码分析09——TreeSet、TreeMap源码分析

TreeSet源码分析

  • 基本介绍:

TreeSet实现了Set接口

  1.在使用无参构造器创建TreeSet对象时,依旧是无序的(写入和取出顺序)

  2.可以使用treeset的一个构造器向其中传入比较器的方式来实现字符排序(匿名内部类),并制定排序规则

package collection.set.treeset;

import java.util.Comparator;
import java.util.TreeSet;

/**
 * @author 紫英
 * @version 1.0
 * @discription
 */
public class Treeset01 {
    public static void main(String[] args) {
        TreeSet treeSet = new TreeSet(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).compareTo((String) o2);
            }
        });

        treeSet.add("jack");
        treeSet.add("a");
        treeSet.add("sda");
        treeSet.add("AAA");
        treeSet.add("66");
        treeSet.add("45");
        treeSet.add("bacf");
        System.out.println(treeSet);
    }
}

debug一下可以看到通过这条语句将传入的comparator赋给了TreeSet底层的TreeMap的一个属性

public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }

//这里再进去
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;

调用后面几条add()语句的时候会在底层调用:

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
                    return t.setValue(value); //如果key相等就返回,t.setValue(value)即替换value,
                              对于单列的set来说就是不添加(因为都是PERSENT)
}
while (t != null); }

 

这里假如我i们改变一下比较规则,改成字符串的长度比较

TreeSet treeSet = new TreeSet(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).length()-((String) o2).length();
            }
        });

这样的话相同长度的字符串就会被判定为相同,不会添加进去,也就是走上边的else语句

 

所以咱们就是说,如果用带compartor的构造器,判定是否写入的规则就是自己定的,上边else语句返回0的情况就视为相同数据

 else
                    return t.setValue(value); 就这个

 

 TreeMap源码分析

把单列集合TreeSet中的value PERSENT替换成了对应的value,实现了Map接口

package collection.map.treemap;

import java.util.Comparator;
import java.util.TreeMap;

/**
 * @author 紫英
 * @version 1.0
 * @discription
 */
public class TreeMap01 {
    public static void main(String[] args) {
        TreeMap treeMap = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).compareTo((String)o2); //比较字符串值的大小
            }
        });
        treeMap.put("jack","杰克");
        treeMap.put("tom","汤姆");
        treeMap.put("smith","史密斯");
        treeMap.put("yigeiwoligiao","小阿giao");
        System.out.println(treeMap);
    }
}

 

 

  1.构造器语句——把传入的实现了Comparator接口的匿名内部类(对象),传给了TreeMap的comparator

 public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }

  2.调用put()方法

  2.1第一次添加的时候,把k-v值封装到Entry对象(相当于hashmap中的Node节点),放入root

Entry<K,V> t = root;
        if (t == null) {
            compare(key, key); // type (and possibly null) check 这里调用compare方法不会影响添加结果,但如果key值为空会抛出一个异常
                                           NullPointerException
            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
                    return t.setValue(value);//遍历过程中如果发现有判定key相等的情况就不添加(相当于之前的equals方法),而是修改value,
                              比如上面的长度比较器,相同长度的key不会被添加进去而是会修改成对应的value  
}
while (t != null); }

 

posted @ 2022-01-22 00:03  紫英626  阅读(24)  评论(0编辑  收藏  举报

紫英