转载自: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); } }