物件排序 — java 7 collection詳解(三)
阿新 • • 發佈:2019-02-03
轉載自:http://peiquan.blog.51cto.com/7518552/1293970
一、基礎補充
- 在 Java 應用程式執行期間,如果物件進行equals比較時沒有被修改任何資訊,那麼同一物件多次呼叫 hashCode方法,必須一致地返回相同的整數。同一程式的兩次執行,該整數無需保持一致。
- 如果根據 equals(Object) 方法判斷出兩個物件是相等的,那麼對這兩個物件中的每個物件呼叫
hashCode
方法都必須生成相同的整數結果。 - 如果根據
equals(java.lang.Object)
方法,兩個物件不相等,那麼對這兩個物件中的任一物件上呼叫 hashCode方法不 要求一定生成不同的整數結果。但是,應該意識到,為不相等的物件生成不同整數結果可以提高雜湊表的效能。
- 自反性:對於任何非空引用值
x
,x.equals(x)
都應返回true
。 - 對稱性:對於任何非空引用值
x
和y
,當且僅當y.equals(x)
返回true
時,x.equals(y)
才應返回true
。 - 傳遞性:對於任何非空引用值
x
、y
和z
,如果x.equals(y)
返回true
,並且y.equals(z)
返回true
,那麼x.equals(z)
應返回true
。 - 一致性:對於任何非空引用值
x
和y
,如果物件進行equals比較時沒有被修改任何資訊,多次呼叫 x.equals(y)始終返回true
或始終返回false。
- 對於任何非空引用值
x
,x.equals(null)
都應返回false
。
public class Student { private String grade; private String name; public Student(String grade, String name) { super(); this.grade = grade; this.name = name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((grade == null) ? 0 : grade.hashCode()); 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 (!(obj instanceof Student)) return false; Student other = (Student) obj; if (grade == null) { if (other.grade != null) return false; } else if (!grade.equals(other.grade)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } public static void main(String[] args) { Student stu1 = new Student("7班", "張三"); Student stu2 = new Student("7班", "張三"); Student stu3 = new Student("7班", "李四"); System.out.println(stu1.equals(stu2)); //true System.out.println(stu1.hashCode() == stu2.hashCode());//true System.out.println(stu1.equals(stu3)); //false System.out.println(stu1 == stu2); //false } }
String[] fruits = new String[]{"orange","Apple","pair","watermelon"}; Arrays.sort(fruits); for (String str : fruits) { System.out.print(str + ""); }
public interface Comparable<T> { public int compareTo(T o); }
在Comparable接口裡只定義了compareTo(obj)方法,用來獲得此物件與指定物件obj的順序。如果該物件小於、等於或大於指定物件obj,則分別返回負整數、零或正整數。如果兩個物件不能相互比較(大小),此方法會丟擲ClassCastException。
public class Student implements Comparable<Student> { private int Id; private int score; private String name; public Student(int id, int score, String name) { super(); if (name == null) { throw new NullPointerException(); } Id = id; this.score = score; this.name = name; } //按照Id值得大小,升序輸出 @Override public int compareTo(Student stu) { return Id > stu.Id ? 1 : (Id < stu.Id ? -1 : 0);
} //為了輸出的方便和排版,重寫toString方法,只是輸出Id的值 @Override public String toString() { return String.valueOf(Id); } public static void main(String[] args) { Student[] stu = {new Student(102, 60, "張三"), new Student(101, 70, "李四"), new Student(103, 90, "王五") }; List<Student> stuList = Arrays.asList(stu); //未排序前的物件順序 System.out.println("未排序前的物件順序:" + stuList); //以自然邏輯排序的物件順序,即Comparable定義的排序邏輯(Id值得大小) Collections.sort(stuList); System.out.println("自然邏輯排序的物件順序:" + stuList); } }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Id; result = prime * result + name.hashCode(); result = prime * result + score; return result; } @Override public boolean equals(Object obj) { if (!(obj instanceof Student)) return false; Student other = (Student) obj; return (Id == other.Id) && (score == other.score) && (name.equals(other.name)); }
這樣Student.java的邏輯就算比較完善了,如果你曾經重寫過equals和hasCode方法,會發現這裡的重寫方法裡沒有考慮到null異常(因為在建構函式裡,確保裡Student的物件 不會包含null,所有不需要考慮null異常)。溫馨提示一下,對於eclipse和netbeans都提供了比較完善的關於equals和hasCode的重寫方法,以eclipse為例,可以按快捷鍵ctrl+shift+S,接著選擇重寫equals()和hasCode()方法。
三、Comparator介面
public interface Comparator<T> { int compare(T o1, T o2); }
在Comparator介面也只是定義裡一個compare方法,用來定義物件的排序邏輯,如果物件o1小於、等於或大於物件o2,則分別返回負整數、零或正整數。如果兩個物件不能相互比較(大小),此方法會丟擲ClassCastException。
public class Student2 { private int Id; private int score; private String name; public Student2(int id, int score, String name) { super(); if (name == null) { throw new NullPointerException(); } this.Id = id; this.score = score; this.name = name; } //為了輸出的方便和排版,重寫toString方法,只是輸出Id的值 @Override public String toString() { return String.valueOf(Id); } public static class OrderById implements Comparator<Student2>{ @Override public int compare(Student2 stu1, Student2 stu2) { return stu1.Id > stu2.Id ? 1:(stu1.Id < stu2.Id ? -1:0); } } public static void main(String[] args) { Student2[] stu = {new Student2(102, 60, "張三"), new Student2(101, 70, "李四"), new Student2(103, 90, "王五") }; List<Student2> stuList = Arrays.asList(stu); //未排序前的物件順序 System.out.println("未排序前的物件順序:" + stuList); //以Comparator定義的排序輸出物件(Id值得大小) Collections.sort(stuList,new Student2.OrderById()); System.out.println("自然邏輯排序的物件順序:" + stuList); } }
public class Student implements Comparable<Student> { private int Id; private int score; private String name; public Student(int id, int score, String name) { super(); if (name == null) { throw new NullPointerException(); } Id = id; this.score = score; this.name = name; } // 為了輸出的方便和排版,重寫toString方法,只是輸出Id的值 @Override public String toString() { return String.valueOf(Id); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Id; result = prime * result + name.hashCode(); result = prime * result + score; return result; } @Override public boolean equals(Object obj) { if (!(obj instanceof Student)) return false; Student other = (Student) obj; return (Id == other.Id) && (score == other.score) && (name.equals(other.name)); } // 按照Id值得大小,升序輸出 @Override public int compareTo(Student stu) { return Id > stu.Id ? 1 : (Id < stu.Id ? -1 : 0); // return score > stu.score ? 1:(score < stu.score ? -1:0); } // 按照分數的高低排序 static final Comparator<Student> ORDERBYSCORE_ORDER = new Comparator<Student>() { @Override public int compare(Student stu1, Student stu2) { return stu1.score > stu2.score ? 1 : (stu1.score < stu2.score ? -1 : 0); } }; // 按姓名的字典順序排序 static final Comparator<Student> ORDERBYNAME_ORDER = new Comparator<Student>() { @Override public int compare(Student stu1, Student stu2) { return stu1.name.compareTo(stu2.name); } }; public static void main(String[] args) { Student[] stu = { new Student(102, 60, "張三"), new Student(101, 70, "李四"), new Student(103, 90, "王五") }; List<Student> stuList = Arrays.asList(stu); // 未排序前的物件順序 System.out.println("未排序前的物件順序:" + stuList); // 以自然邏輯排序的物件順序,Comparable定義的邏輯 Collections.sort(stuList); System.out.println("自然邏輯排序的物件順序:" + stuList); // 降序排序輸出物件 Collections.sort(stuList, Collections.reverseOrder()); System.out.println("降序排序輸出物件:" + stuList); // 使用Comparator順序輸出物件,OederByScore Collections.sort(stuList, ORDERBYSCORE_ORDER); System.out.println("OederByScore順序輸出物件" + stuList); // 使用另一個Comparator順序輸出物件,OederByName Collections.sort(stuList, ORDERBYNAME_ORDER); System.out.println("OederByName順序輸出物件" + stuList); } }