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

xiaoxiao2021-02-28  68

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是一个包装类,包装了许多操作集合的静态方法。就相当于一个工具类。

转载请注明原文地址: https://www.6miu.com/read-73335.html

最新回复(0)