TreeMap和TreeSet在排序時如何比較元素?Collections工具類中的sort()方法如何比較元素?
阿新 • • 發佈:2019-01-27
TreeMap和TreeSet都是有序的集合。
TreeSet要求集合中的元素實現Comparable介面,並實現compareTo方法進行比較,如果compareTo方法實現的不好,可能會導致元素插入失敗,因為集合內部也通過compareTo方法來比較元素是否相等(而不是通過equals),即判斷一個元素是否可插入。
TreeMap要求鍵列的元素實現Comparable介面,與TreeSet對元素的要求一樣。
TreeSet其實內部是通過一個TreeMap來實現的,用了組合的設計模式。
我們來看下原始碼
可以看到,在構造TreeSet時,也構造了一個TreeMap,並且Map中的value不使用。/** * 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的add方法,其實是呼叫了TreeMap的put方法,我們再看一下原始碼。
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
PRESENT是一個Object物件,沒有實際意義,現在我們進入TreeMap看一下put方法的原始碼。
我們可以看到,方法內是通過元素實現Comparable介面並實現了的compareTo方法來比較兩個key是否相等的。並且進行排序。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; }
第二個問題:
Collections有兩個sort方法,可以僅僅傳入一個由實現了Comparable介面元素構成的List物件,當然也可以傳入集合中的元素沒有實現Comparable的List物件,但是要求傳入第二個引數,引數是Comparator介面的子型別(需要重寫compare方法實現元素的比較),相當於一個臨時定義的排序規則,其實就是通過介面注入比較元素大小的演算法,也是對回撥模式的應用(Java中對函數語言程式設計的支援)。
另外一點,
Collection和Collections有很大區別,Collection是是一個 集合介面。它提供了對集合物件進行基本操作的通用介面方法。Collection介面在Java
類庫中有很多具體的實現。Collection介面的意義是為各種具體的集合提供了最大化的統一操作方式。
而Collections是一個包裝類,包裝了許多操作集合的靜態方法。就相當於一個工具類。