練習:
存盤學生物件并遍歷,創建TreeSet集合使用無參構造方法,并按照年齡從小到大的順序排序,若年齡相同再按照姓名的字母順序排序
分析:
1.創建學生類,成員變數name,age;無參構造,帶參構造;get\set方法;
2.創建測驗類,添加資料并進行排序;直接排序會報錯
3.需要Student實作comparable介面并重寫Comparable中的compareto方法來實作按照我們給定的順序排序
Student類代碼
public class Student{
//成員變數
private String name;
private int age;
//構造方法
public Student(){}
public Student(String name,int age){
this.age=age;
this.name=name;
}
//get\set方法
?
public String getName() {
return name;
}
?
public void setName(String name) {
this.name = name;
}
?
public int getAge() {
return age;
}
?
public void setAge(int age) {
this.age = age;
}
}
測驗類
public class StudentDemo {
public static void main(String[] args) {
//創建TreeSet物件
TreeSet<Student>ts=new TreeSet<Student>();
//創建學生物件
Student s=new Student("張三",18);
Student s1=new Student("張四",17);
Student s2=new Student("張五",19);
Student s3=new Student("張六",12);
//添加資料
ts.add(s);
ts.add(s1);
ts.add(s2);
ts.add(s3);
//遍歷
for (Student ss:ts){
System.out.println(ss.getName()+ss.getAge());
}
}
?
}
?
第一次運行結果提示Student cannot be cast to java.lang.Comparable,這個時候我們就需要在Student類實作comparable介面重寫compareto方法,并給定回傳值
public class Student implements Comparable<Student>{
//成員變數
private String name;
private int age;
//構造方法
public Student(){}
public Student(String name,int age){
this.age=age;
this.name=name;
}
//get\set方法
?
public String getName() {
return name;
}
?
public void setName(String name) {
this.name = name;
}
?
public int getAge() {
return age;
}
?
public void setAge(int age) {
this.age = age;
}
?
@Override
public int compareTo(Student o) {
// return 0;
// return 1;
// return-1;
}
}
那么可以看到compareto方法中有三個回傳值分別是0、1、-1三種情況;
1.return 0:回傳值是0的情況下再遍歷集合只會在控制臺列印出第一個元素;這是因為存入第一個元素時不需要比較直接存入集合,第二個 元素再存入是就需要跟第一個元素比較,但回傳值為0,就會認為第二個元素跟第一個元素是相同的、重復的,就不存盤,依此類推
2.return 1:回傳值是1的情況下再遍歷集合會按照存盤資料的順序在控制臺全部列印出來;同樣的,第一個元素存入不比較,第二個元素與第一個元素比較,回傳值為1;就會認為第二個元素比第一個元素大,排在第一個元素后面,以此類推
3.return -1:與renturn 1的情況相反,也就是會按照存盤資料順序的倒序方式在控制臺列印出來
思考:我們需要按照年齡的大小排序,這本質上不是只要回傳值是一個正數就行了嘛,那我們就可以在compareto方法中這樣寫
public int compareTo(Student s) {
//return 0;
//return 1;
int num=this.age-s.age;
return num;
}
其中,this是方法內部就有的,在這里this.age代表當第一個元素存盤后的后續每一個元素的年齡,我們用后續存盤的元素年齡減去第一個元素的年齡當結果是-1時,就將該元素排在第一個元素前面,為1時,就排在后面,為0時就代表重復不存盤
但是在我們完成按照年齡進行排序后有出現一個問題:當兩個元素姓名不同年齡相同時,再按照我們設定的規則就不會將年齡相同的最后一個元素存盤進去,因為它們兩個年齡相減為0,默認重復了,所以在年齡相同的情況下,我們還要再比較姓名,如下
public int compareTo(Student s) {
//return 0;
//return 1;
int num=this.age-s.age;
int num1=num==0?this.name.compareTo(s.name):num;
return num1;
?
}
當年齡不同時回傳的還是之前num的值,當年齡相同時比較姓名是否相同不相同回傳1代表可以進行存盤,相同回傳0代表重復,
在這里因為string 本身就實作了comparable介面,所以可以直接呼叫compareto方法,這樣就很好的解決了問題又保證了資料的唯一性
總結:
1.TreeSet集合存盤自定義物件時,無參構造方法使用的是自然排序也就是按照存盤元素的順序進行排序
2.自然排序也就是讓元素所屬的類實作Comparable介面,重寫compareto(T o)方法
3.重寫compareto(T o)方法時,一定要注意排序規則必須按照要求的主要條件和次要條件來寫
比較器排序Comparator
練習:
存盤學生物件并遍歷,創建TreeSet集合使用帶參構造方法,并按照年齡從小到大的順序排序,若年齡相同再按照姓名的字母順序排序
分析:較于comparable來說,comparator無需在Student類中實作comparable介面,可以直接在創建TreeSet集合物件時使用內部類的方式進行
public class StudentDemo {
public static void main(String[] args) {
//創建TreeSet物件
TreeSet<Student>ts=new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num =s1.getAge()-s2.getAge();
int num1=num==0?s1.getName().compareTo(s2.getName()):num;
return num1;
}
});
//創建學生物件
Student s=new Student("張三",18);
Student s1=new Student("張四",17);
Student s2=new Student("張五",19);
Student s3=new Student("張六",12);
Student s4=new Student("張七",12);
//添加資料
ts.add(s);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
for (Student ss:ts){
System.out.println(ss.getName()+ss.getAge());
}
}
?
}
?
其中需要注意的是,compare方法傳遞了兩個引數,s1就等同于compareto中的this,但由于內部類無法直接訪問Student類的私有成員變數,只能通過get方式來獲取,效果等同于自然排序Comparable
感謝1樓前輩給出的指導,文中出現的錯誤與更正如下:
1.TreeSet集合存盤自定義物件時,無參構造方法使用的是自然排序也就是按照存盤元素的順序進行排序) 正確的總結:使用TreeSet時,要么實作Comparable介面,要么指定Comparator,兩者并存時優先使用Comparator,否則add方法報錯cannot be cast to java.lang.Comparable,
可以在TreeMap中找到原始碼:
/**
* Compares two keys using the correct comparison method for this TreeMap.
*/
@SuppressWarnings("unchecked")
final int compare(Object k1, Object k2) {
return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
: comparator.compare((K)k1, (K)k2);
}
// Student未實作Comparable介面時,初始化TreeSet時,需指定Comparator
TreeSet<Student> ts2 = new TreeSet<>(Comparator.comparingInt(Student::getAge).thenComparing(Student::getName));
ts.add(new Student("張三", 18));
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/451989.html
標籤:其他
上一篇:【JavaWeb-jQuery】筆記(1)--- jQuery概述;dom物件和jquery物件;jQuery選擇器;jQuery過濾器
