1. 程式人生 > >java集合——樹集(TreeSet)+物件的比較

java集合——樹集(TreeSet)+物件的比較

【0】README

【1】樹集(TreeSet)(用到了紅黑樹)

1.1)樹集是一個有序集合。可以以任意順序將元素插入到集合中, 在對集合進行遍歷時,每個值將自動地按照排序後的順序呈現;

  • 1.1.1)看個荔枝:
SortedSet<String> sorter = new TreeSet<>(); // TreeSet implements SortedSet
sorter.add("bob");
sorter.add("car");
sorter.add("amy");
for(String s: sorter)
    System.println(s);

1.1.2)將元素新增到 樹(TreeSet)中要比新增到散列表(HashSet)中慢, 但是,與將元素新增到陣列或連結串列的正確位置上相比還是快很多的;
這裡寫圖片描述
這裡寫圖片描述
Attention) TreeSet 的排序功能用到了紅黑樹, 因此迭代器總是以排好序的順序訪問每個元素)

API java.util.TreeSet<E> 1.2
TreeSet():構造一個空樹集;
TreeSet(Collection<? extends E> elements):構造一個樹集, 並將集合中所有元素新增到樹集中;

【2】物件的比較

2.1) TreeSet如何知道希望元素怎樣排列呢? 在預設情況下, 樹集假定插入的元素實現了 Comparable 介面, 這個介面定義了一個方法:

public interface Comparable<T>
{
    in compareTo(T other);
}
  • 2.1.1)排序後,a在b的前面,後面或相等,分別返回 負值,正值,0;
  • 2.1.2)有些標準的 java 平臺類實現了 Comparable介面,如, String類, 這個類的compareTo() 方法依據字典順序對字串進行比較;

2.2)如果要插入自定義物件, 就必須通過實現 Comparable介面自定義排列順序。

  • Attention)在 Object類中, 沒有提供任何 compareTo 介面的預設實現 (乾貨);
  • 2.2.1)看個荔枝:(展示瞭如何用部件編號對 Item 物件進行排序)
class Item implements Comparable<Item>
{
    public int compareTo(Item other)
    {
        return partNumber - other.partNumber;
    }    
}
  • Warning)只有整數在一個足夠小的範圍內,才可以使用這個技巧。 如果x是一個較大的正整數, y是一個較大的負整數, x-y 有可能會溢位;

2.3)出現的問題+解決方法

  • 2.3.1)出現的問題:使用 Comparable介面定義排列排序顯然有其侷限性。對於一個給定的類, 只能實現這個介面一次。如果在一個集合中需要按照部件編號進行排序, 在另一個集合中 卻要按照描述資訊進行排序, 該怎麼辦呢?還有,如果需要對一個類的物件進行排序, 而這個類的建立者又沒有實現 Comparable介面, 又該怎麼辦呢?
  • 2.3.2)解決方法: 通過將 Comparator 物件傳遞給TreeSet構造器來告訴樹集使用不同的比較方法。 Comparator介面聲明瞭一個帶有兩個顯式引數的compare 方法:
public interface Comparator<T>
{
    int compare(T a, T b);
}
  • (即, 當兩個不同集合中的元素的排序規則不同, 就要引入Comparator)
  • 2.3.2.1)與 compareTo() 方法一樣,a在b之前,之後,或相等, 分別返回 正值, 負值和零;所以,我們直接定義一個 實現 Comparator 介面的類:
class ItemComparator implements Comparator<Item>
{
    public int compare(Item a, Item b)
    {
          String desrcA = a.getDescription();
          String desrcB = b.getDescription();
          String desrcA.compareTo(desrcB);
    }
}
  • 2.3.2.2)然後將這個類物件傳遞給樹集的構造器:
ItemComparator comp =  new ItemComparator();
SortedSort<Item> sort = new TreeSet<>(comp);
  • Attention)

    • A1) 注意, 這個比較器沒有任何資料, 它只是比較方法的持有器。有時將這種物件稱為函式物件。
    • A2)函式物件通常動態定義, 即定義為匿名內部類的例項:
SortedSet<Item> set = new TreeSet<>(new 
    Comparable<Item>(){    //匿名 內部類;
     public int compare(Item a, Item b) // 匿名內部類中的方法;
        {
              String desrcA = a.getDescription();
              String desrcB = b.getDescription();
              String desrcA.compareTo(desrcB);
        }
});

Annotation)

  • A1)實際上, Comparator 介面聲明瞭兩個方法:compare 和 equals;
  • A2)當然,每個類都有一個 equals 方法, 因此, 為這個介面宣告再新增一個 equals 方法似乎沒有太大的好處;
  • A3) API文件說, 不需要覆蓋equals 方法, 但這樣做可能會在某些情況下 提高效能;

2.4)下面的圖是否給了我們的疑慮:是否總應該用 樹集(TreeSet)取代雜湊集(HashSet)?
這裡寫圖片描述

  • 2.4.1)因為新增一個元素所花費的時間看上去並不很長, 而且元素時自動排序的;
  • 2.4.2)到底應該怎樣做將取決於 所要收集的資料。如果不需要對資料進行排序,就沒有必要付出排序開銷 (乾貨,如何選擇集型別, 是樹集TreeSet 還是 雜湊集 HashSet)。
  • 2.4.3)更重要的是, 對其排序要比 雜湊函式更加困難, 因為雜湊函式只是將物件適
    這裡寫圖片描述

2.5)收集矩形集(just for coarse understanding):想具體瞭解樹集和雜湊集間的差異, 還需要研究一個收集矩形集的任務。如果使用 TreeSet, 就需要提供 Comparator;

  • 2.5.1)如何比較兩個矩形呢? 比較面積嗎。這行不通。可能會有兩個不同的矩形, 它們的座標不同, 但面積卻相同。 樹的排序必須是全序的。也就是說, 任意兩個元素是可比的,並且只有在兩個元素相等時才return 0;
  • 2.5.2)確實, 有一種矩形的排序方式, (按照座標的字典順序排序), 但它的計算很牽強且很繁瑣。 相反地, Rectangle 類已經定義了雜湊函式, 它直接對座標進行雜湊;

Annotation) 從 Java SE 6 開始, TreeSet 類實現了 NavigableSet 介面。 這個介面增加了幾個便於定位元素以及反向遍歷的方法;

2.6)看個荔枝:(下面的程式建立了兩個 Item 物件的樹集, 第一個按照部件編號排序, 這是Item物件的預設順序。第二個通過使用一個定製的比較器來按照描述資訊排序-)
這裡寫圖片描述
這裡寫圖片描述

Complementary)我們給出 Integer 原始碼 的 Comparatable 實現:

這裡寫圖片描述

java.lang.Comparable<T> 1.2
int compareTo(T other) :將this 和 other 進行比較, 返回 正值、負值和0;

java.util.Comparator<T> 1.2
int compare(T a, T b): 將a 和 b進行比較, 返回 正值、負值和0;

java.util.SortedSet<T> 1.2
Comparator<? super E> comparator() :返回用於對元素進行排序的比較器, 如果元素用 Comparable 介面的compareTo 方法比較則返回 null;
E first();
E last();
返回有序集中的最小最大元素;

java.util.NavigableSet<E> 6
E higher(E value)
E lower(E value)
返回大於 value 的最小元素或小於 value 的最大元素,否則返回 null;

E ceiling(E value)
E floor(E value)
返回大於等於 value 的最小元素或小於等於 value 的最大元素,否則返回 null;

E pollFirst(E value)
E pollLast(E value)
刪除並返回這個集中的最大元素或最小元素, 這個集為空時返回 null;

Iterator<E> descendingIterator():返回一個按照 遞減順序遍歷集合中元素的迭代器;

java.util.TreeSet<E> 1.2
TreeSet() :構造一個用於 排列 Comparable 物件的樹集;
TreeSet(Comparator<? super E > c ):構造一個樹集, 並使用指定的比較器對其中的元素進行排序;
TreeSet(SortedSet<? extends E> elements):構造一個樹集, 將有序集中的所有元素新增到這個樹集中, 並使用與給定集合相同的元素比較器;