java集合框架之TreeSet類

1.TreeSet介紹

TreeSet集合底層採用紅黑樹算法,會對存儲的元素默認使用自然排序(從小到大).
注意: 必須保證TreeSet集合中的元素對象是相同的數據類型,否則報錯.


2.TreeSet的排序規則

自然排序(從小到大):
TreeSet調用集合元素的compareTo方法來比較元素的大小關係,然後將集合元素按照升序排列(從小到大).
注意:要求TreeSet集合中元素得實現java.util.Comparable接口.

各種數據類型自然排序規則


java.util.Comparable接口:可比較的.
覆蓋 public int compareTo(Object o)方法,在該方法中編寫比較規則.
在該方法中,比較當前對象(this)和參數對象o做比較(嚴格上說比較的是對象中的數據,比如按照對象的年齡排序).
       this  >  o: 返回正整數.  1
       this <   o: 返回負整數.  -1
       this == o: 返回0.     此時認爲兩個對象爲同一個對象.
--------------------------------------
在TreeSet的自然排序中,認爲如果兩個對象做比較的compareTo方法返回的是0,則認爲是同一個對象.


從上圖可知,基本上很多類都實現了這個接口,我們來看一下String類源碼,可以看出String已經實現Comparable,並覆蓋compareTo方法



舉例:

import java.util.Set;
import java.util.TreeSet;

public class SetDemo4 {
	public static void main(String[] args) {
		Set<String> set = new TreeSet<>();
		
		set.add("a");
		set.add("A");
		set.add("abc");
		set.add("B");
		
		System.out.println(set);//打印結果,已經排好序了[A, B, a, abc],按照字符串的Unicode值排序
	}
}
在這裏我們如果要想自己定義的類在TreeSet中也能實現自然排序,那麼就要根據上面的步驟來實現:

舉個例子:首先定義一個Student類,這個類要實現Comparable接口,然後覆蓋CompareTo方法,自定義自己需要排序的規則,比如我們這裏按照學生的姓名的長度進行自然排序:

class Student implements Comparable<Student>{
	private int id;
	private String name;
	
	public Student(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + "]";
	}

	/**
	 * 覆蓋compareTo方法
	 * 根據學生的姓名長度排序
	 */
	public int compareTo(Student stu) {
		if (this.getName().length()>stu.getName().length()) {
			return 1; 
		}else if (this.getName().length()<stu.getName().length()) {
			return -1;
		}else {
			return 0; //長度相同
		}
	}
	
}
測試:打印結果,姓名長度由短到長來排序的

import java.util.Set;
import java.util.TreeSet;

public class SetDemo4 {
	public static void main(String[] args) {
		Set<Student> set = new TreeSet<>();
		
		set.add(new Student(1, "聶小倩"));
		set.add(new Student(1, "西門吹雪"));
		set.add(new Student(1, "哥"));
		set.add(new Student(1, "孫斌"));
		
		System.out.println(set);
		//打印結果看下面,說明是按照名字長度從小到大的自然順序來排序的
		//[Student [id=1, name=哥], Student [id=1, name=孫斌], Student [id=1, name=聶小倩], Student [id=1, name=西門吹雪]]
	}
}


定製排序(比如從大到小,按照名字的長短來排序):
TreeSet構造器中傳遞java.lang.Comparator對象.覆蓋public int compare(Object o1, Object o2)再編寫比較規則.

在TreeSet構造函數中,有一個構造函數可以傳入一個比較器對象,他是一個接口,我們需要提供實現類,並覆蓋compare方法再編寫比較規則.


同樣的,我們舉個例子,也是按照學生姓名長度排序:

首先也是定義一個學生類:

class Student{
	private int id;
	private String name;
	
	public Student(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + "]";
	}	
}
然後定義比較器類:

import java.util.Comparator;

//比較器類
class NameLengthComparator implements Comparator<Student> {
	/**
	 * 覆蓋compare方法
	 * 比較規則:同樣是根據學生的姓名長度排序
	 */
	public int compare(Student s1, Student s2) {
		if (s1.getName().length() > s2.getName().length()) {
			return 1;
		} else if (s1.getName().length() < s2.getName().length()) {
			return -1;
		} else {
			return 0;
		}
	}

}
測試:

import java.util.Set;
import java.util.TreeSet;

public class SetDemo5 {
	public static void main(String[] args) {
		//創建set對象的時候要傳入比較器類對象
		Set<Student> set = new TreeSet<>(new NameLengthComparator());

		set.add(new Student(1, "聶小倩"));
		set.add(new Student(1, "西門吹雪"));
		set.add(new Student(1, "哥"));
		set.add(new Student(1, "孫斌"));

		System.out.println(set);
	}
}
打印結果:

[Student2 [id=1, name=哥], Student2 [id=1, name=孫斌], Student2 [id=1, name=聶小倩], Student2 [id=1, name=西門吹雪]]

既然是定製排序,你可以修改排序規則,按照從長到短來排序,只需要修改比較器類的實現規則

import java.util.Comparator;

//比較器類
class NameLengthComparator implements Comparator<Student> {
	/**
	 * 覆蓋compare方法
	 * 比較規則:同樣是根據學生的姓名長度排序
	 */
	public int compare(Student s1, Student s2) {
		if (s1.getName().length() < s2.getName().length()) {
			return 1;
		} else if (s1.getName().length() > s2.getName().length()) {
			return -1;
		} else {
			return 0;
		}
	}

}
將if中的>和<修改一下就行了

對於TreeSet集合來說,要麼使用自然排序,要麼使用定製排序.
判斷兩個對象是否相等的規則:
自然排序:   compareTo方法返回0;
定製排序:  compare方法返回0;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章