淺談java中的TreeSet中的排序方式
阿新 • • 發佈:2018-12-25
TreeSet 和HashSet的區別
- HashSet是通過HashMap實現的,TreeSet是通過TreeMap實現的,只不過Set用的只是Map的key
- Map的key和Set都有一個共同的特性就是集合的唯一性.TreeMap更是多了一個排序的功能.
- hashCode和equal()是HashMap用的, 因為無需排序所以只需要關注定位和唯一性即可.
a. hashCode是用來計算hash值的,hash值是用來確定hash表索引的.
b. hash表中的一個索引處存放的是一張連結串列, 所以還要通過equal方法迴圈比較鏈上的每一個物件
才可以真正定位到鍵值對應的Entry.
c. put時,如果hash表中沒定位到,就在連結串列前加一個Entry,如果定位到了,則更換Entry中的value,並返回舊value - 由於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()方法的返回值為正則前後兩個元素位置要發生交換
返回值為負則前後兩個元素位置不發生交換
**