TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?
原创LiQiyaoo
展开
TreeMap和TreeSet都是有序的集合。
TreeSet要求集合中的元素实现Comparable接口,并实现compareTo方法进行比较,如果compareTo方法实现的不好,可能会导致元素插入失败,因为集合内部也通过compareTo方法来比较元素是否相等(而不是通过equals),即判断一个元素是否可插入。
TreeMap要求键列的元素实现Comparable接口,与TreeSet对元素的要求一样。
TreeSet其实内部是通过一个TreeMap来实现的,用了组合的设计模式。
我们来看下源码
/**
* The backing map.
*/
private transient NavigableMap<E,Object> m;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public TreeSet() {
this(new TreeMap<E,Object>());
}
可以看到,在构造TreeSet时,也构造了一个TreeMap,并且Map中的value不使用。
我们调用TreeSet的add方法,其实是调用了TreeMap的put方法,我们再看一下源码。
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
PRESENT是一个Object对象,没有实际意义,现在我们进入TreeMap看一下put方法的源码。
public V put(K key, V value) {
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;
}
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 t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
@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 t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
我们可以看到,方法内是通过元素实现Comparable接口并实现了的compareTo方法来比较两个key是否相等的。并且进行排序。
第二个问题:
Collections有两个sort方法,可以仅仅传入一个由实现了Comparable接口元素构成的List对象,当然也可以传入集合中的元素没有实现Comparable的List对象,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)。
另外一点,
Collection和Collections有很大区别,Collection是 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
而Collections是一个包装类,包装了许多操作集合的静态方法。就相当于一个工具类。
————————————————
版权声明:本文为CSDN博主「LiQiyaoo」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/L_BestCoder/article/details/77771412