集合源码分析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); }
本文来自博客园,作者:紫英626,转载请注明原文链接:https://www.cnblogs.com/recorderM/p/15832216.html