TreeSet去重分两种,第一种是我们重写了Comparator匿名类,第二种则是没有重写。
一,我们先分析一下没有重写的情况,当我们没有重写Comparator匿名类时
首先可以看看TreeSet的主要去重源代码
public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Objects.requireNonNull(value);
Entry<K,V> t = root;
if (t == null) {
addEntryToEmptyMap(key, value);
return value;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else return mergeValue(t, value, remappingFunction);
} while (t != null);
} else {
Objects.requireNonNull(key);
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else return mergeValue(t, value, remappingFunction);
} while (t != null);
}
addEntry(key, value, parent, cmp < 0);
return value;
}可以看到上方的源代码,当我们没有重写Comparator匿名类时 ,TreeMap自身的Comparator属性就是null,赋给cpr。cpr为null,故不会执行第一个if条件语句,转而执行第二个else条件语句,也就是紫色部分,进去之后,执行到深绿色的代码时,此部分会将key向上转型成Comparable类型,因为key这个时候已经是String类型,而String类型实现了Comparable接口,所以可以用多态的方式结构实现接口的方法,往后就进入do,while循环调用String的compare方法比较字母大小,按字母的大小进行排序,如果字母大小一致,则返回0赋予cmp,cmp=0则执行红色代码块的语句。
版权声明:本文为m0_58229878原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。