TreeSet的自然排序(Comparable)與定製排序(Compartor)
阿新 • • 發佈:2018-12-19
TreeSet
TreeSet 儲存自定義物件
cannot be cast tojava.lang.Comparable,遇到這個異常錯誤,就是說treeMap(或者treeSet)並不知道該如何put(add),就會報這個異常錯誤。
- 自定義的物件需要實現Comparable介面。(String除外)
自然排序與定製排序的比較
-
兩種方法各有優劣, 用Comparable 簡單, 只要實現Comparable 介面的物件直接就成為一個可以比較的物件
但是需要修改原始碼。 -
用Comparator 的好處是不需要修改原始碼, 而是另外實現一個比較器, 當某個自定義
的物件需要作比較的時候,把比較器和物件一起傳遞過去就可以比大小了, 並且在Comparator 裡面使用者可以自
己實現複雜的可以通用的邏輯,使其可以匹配一些比較簡單的物件,那樣就可以節省很多重複勞動了。 -
compareTo就是比較兩個值,如果前者大於後者,返回1,等於返回0,小於返回-1,
-
我下面給出了例子,由於比較的變數我用的是int,int型可以直接比較,所有沒有用到compareTo比較,
-
如果宣告的是Date、String、Integer或者其他的,可以直接使用compareTo比較,
java內外部比較器(Comparator、Comparable)
import java.util.*;
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>();
ts.add(new Student("AA", 22));
ts.add(new Student("BB", 20));
ts.add(new Student("CC", 18));
ts.add(new Student("DD", 19));
// Iterator<Student> it = ts.iterator();
// while (it.hasNext()) {
// System.out.println(it.next());
// }
}
}
class Student implements Comparable// 該介面強制讓學生具備比較性
{
private String name;
private int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
public int compareTo(Object obj)// 這個方法在呼叫add方法時候強制預設自動呼叫
{
if (obj instanceof Student) {// 比較的前提:兩個物件的型別相同
Student s = (Student) obj;
/*
* 當採用compareTo(Object obj)方法比較物件時,都需要將被比較物件obj強制型別轉換成相同型別,
* 因為只有相同類的兩個例項才能比較大小
*/
System.out.println(this.name + "比較" + s.name);
return this.name.compareTo(s.name);
}
// if(this.age>s.age)
// return 1;
// if(this.age==s.age)
// {
// return this.name.compareTo(s.name);//String類已經實現CompareTo
// }if(this.age<s.age)
// return -1;
// }
// return 0;
return 0;
}
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
自然排序
注意:
Java 9 改進了 TreeSet 實現,如果採用自然排序的 Set 集合的元素沒有實現 Comparable 介面,程式就會立即引發
ClassCastException
具體實現
package www.xq.collection;
import jdk.nashorn.internal.runtime.regexp.joni.constants.AsmConstants;
import org.junit.Test;
import java.util.Iterator;
import java.util.TreeSet;
/**
* @author xqstart
* @date 2018/10/11 - 15:47
*/
public class TestTreeSet2 {
public static void main(String[] args) {
TreeSet<Student1> students = new TreeSet<Student1>();
students.add(new Student1("aa", 23));// 往集合新增元素
students.add(new Student1("BB", 24));
students.add(new Student1("cc", 34));
students.add(new Student1("dd", 23));
students.add(new Student1("ff", 21));
Iterator<Student1> iterator = students.iterator();//初始化迭代器,遍歷集合中的所有元素
while (iterator.hasNext()) {
Student1 student1 = iterator.next();
System.out.println(student1.getName() + "---->" + student1.getAge());
}
}
}
class Student1 implements Comparable<Object> {
private String name;
private int age;
// 複寫建構函式初始化姓名跟年齡
Student1(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public int compareTo(Object o) {
if(!(o instanceof Student1)) // 第三:判斷物件是否是特定類的一個例項
throw new RuntimeException("不是學生物件");
Student1 s = (Student1)o;
// 第四:當前物件的年齡與插入物件的年齡進行比較,當前年齡大於插入物件的年齡時,返回1,
// 此時將插入二叉樹的右邊,當等於時,返回0,進行次要條件的比較,再次呼叫;當小於時,返回-1;
if (this.age > s.age) // 判斷當前物件年齡是否大於傳入的物件年齡
return 1;
if (this.age == s.age) // 如果當前年齡等於傳入物件的年齡,則比較姓名是否相同
{
return this.name.compareTo(s.name);
}
return -1;
}
}
定製排序
具體實現:
package www.xq.collection;
import java.util.Iterator;
import java.util.TreeSet;
/**
* @author xqstart
* @date 2018/10/11 - 16:39
*/
public class TestTreeSet {
public static void main(String[] args) {
TreeSet<Student> students = new TreeSet<>(new MyComparator());//建立一個 TreeSet 的集合
/**
* 要實現定製排序,需要在建立TreeSet集合物件時,提供一個一個Comparator物件,
* 該物件裡負責集合元素的排序邏輯;
*/
students.add(new Student("aa", 23));// 往集合新增元素
students.add(new Student("BB", 24));
students.add(new Student("cc", 34));
students.add(new Student("dd", 23));
students.add(new Student("ff", 21));
Iterator<Student> iterator = students.iterator();//初始化迭代器,遍歷集合中的所有元素
while (iterator.hasNext()) {
Student student = iterator.next();
System.out.println(student.getName() + "---->" + student.getAge());
}
}
}
Student類設計
package www.xq.collection;
import java.util.Comparator;
/**
* @author xqstart
* @date 2018/10/11 - 15:51
*/
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class MyComparator implements Comparator{ //第一步:實現Comparator介面
@Override
public int compare(Object o1, Object o2) { //第二步:實現一個campare方法
//判斷物件是否是特定類的一個例項
if(o1 instanceof Student & o2 instanceof Student){
Student s1 = (Student)o1;
Student s2 = (Student)o2;
if(s1.getAge() > s2.getAge()){
return 1;
}else if(s1.getAge() < s2.getAge()){
return -1;
}
}
return 0;
}
}