TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?

Posted fangdie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?的主要内容,如果未能解决你的问题,请参考以下文章

TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?

java中的排序--排序容器_TreeSet与TreeMap

TreeMap 的排序冲突吗

TreeSet ------自然排序与定制排序(比较器)

TreeMap and TreeSet

TreeSet和TreeMap不能存放重复元素?能不能存放null?