1. 程式人生 > >淺談java中的TreeSet中的排序方式

淺談java中的TreeSet中的排序方式

TreeSet 和HashSet的區別

  1. HashSet是通過HashMap實現的,TreeSet是通過TreeMap實現的,只不過Set用的只是Map的key
  2. Map的key和Set都有一個共同的特性就是集合的唯一性.TreeMap更是多了一個排序的功能.
  3. hashCode和equal()是HashMap用的, 因為無需排序所以只需要關注定位和唯一性即可.
    a. hashCode是用來計算hash值的,hash值是用來確定hash表索引的.
    b. hash表中的一個索引處存放的是一張連結串列, 所以還要通過equal方法迴圈比較鏈上的每一個物件
    才可以真正定位到鍵值對應的Entry.
    c. put時,如果hash表中沒定位到,就在連結串列前加一個Entry,如果定位到了,則更換Entry中的value,並返回舊value
  4. 由於TreeMap需要排序,所以需要一個Comparator為鍵值進行大小比較.當然也是用Comparator定位的.
    a. Comparator可以在建立TreeMap時指定
    b. 如果建立時沒有確定,那麼就會使用key.compareTo()方法,這就要求key必須實現Comparable介面.
    c. TreeMap是使用Tree資料結構實現的,所以使用compare介面就可以完成定位了.

**看完了上面我們發現 要使用TreeMap 那麼必須在建立TreeMap時指定Comparator
或者TreeMap的key物件實現了Comparable介面 TreeSet同樣也是如此
**

建立TreeSet時指定Comparator

首先建立一個Person 實體類
其中有兩個屬性 name age 其並未實現Comparable 介面

package com.compare.test;

public class Person{

    private String name;
    private int age;

    public Person() {

    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this
.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }

PersonComparator 實現了Comparator 其中 只有一個方法

package com.compare.test;

import java.util.Comparator;

public class PersonComparator implements Comparator<Person> {

    public int compare(Person o1, Person o2) {
        if(o1.getAge()>o2.getAge()){
            return 1;
        }else{
            return -1;
        }


    }

}

測試

package com.compare.test;

import java.util.Iterator;
import java.util.TreeSet;

public class TestPerson {

    public static void main(String[] args) {

        Person p1 = new Person("z3", 15);
        Person p2 = new Person("qw", 30);
        Person p4 = new Person("ww", 23);
        Person p3 = new Person("xc", 10);

        TreeSet<Person> s = new TreeSet<Person>(new PersonComparator());
        s.add(p3);
        s.add(p1);
        s.add(p2);
        s.add(p4);

        Iterator it = s.iterator();

        while(it.hasNext()){
            System.out.println(it.next());
        }
        //System.out.println(s);

    }

}

執行結果

Person [name=xc, age=10]
Person [name=z3, age=15]
Person [name=ww, age=23]
Person [name=qw, age=30]

發現Person 類物件以age 從小到大排序
當我們把PersonComparator 實現了Comparator
方法返回值修改為

public int compare(Person o1, Person o2) {
        if(o1.getAge()>o2.getAge()){
            return -1;
        }else{
            return 1;
        }


    }

這時候 排序則為降序排列

Person [name=qw, age=30]
Person [name=ww, age=23]
Person [name=z3, age=15]
Person [name=xc, age=10]

Person實現了Comparable介面

Person程式碼實現了Comparable 其他同上

public class Person implements Comparable<Person>{

...

public int compareTo(Person o) {
        if(this.age > o.age){
            return 1;
        }else{return -1;}

    }

}

這時候建立TreeSet物件時就不用在構造方法中指定Comparator了

TreeSet<Person> s = new TreeSet<Person>();

其他程式碼同上
執行

Person [name=xc, age=10]
Person [name=z3, age=15]
Person [name=ww, age=23]
Person [name=qw, age=30]

結果為升序

當修改compareto方法中的返回值後 修改方式同上
我們可以發現結果為降序了

總結

我們發現當person類 p1的age屬性大於p2的值時
P1代表前一個值,p2代表後一個值
即p1.age > p2.age
以下方法

public int compareTo(Person o) {
        if(this.age > o.age){
            return 1;
        }else{return -1;}

    }
  • 若為真時:
    若返回正值 兩者位置需要交換
    而p1.age > p2.age 兩者一交換p1在後面p2在前面
    即值大的在後 值小的在前 形成了升序排列
    若返回負值 兩者不需要交換
    而此時 p1.age 值大於p2.age 代表
    值大的p1排在前面 值小的p2排在後面
    形成了降序排列

**即treeset排序根據key.compareTo()方法排序時
若key.compareTo()方法的返回值為正則前後兩個元素位置要發生交換
返回值為負則前後兩個元素位置不發生交換
**