为了让类的对象间可以排序,通常有两种方法——Comparable<T> 与 Comparator<T>。
为了判断两个对象是否相等与Set中去重,通常重写父类的equals()方法。
为了逻辑一致:
强烈建议重写comparableTo()后也重写equals()方法。
Comparable泛型接口
int java.lang.Comparable.
compareTo(T o)
本对象与参数进行对比。返回为负表示本对象小于目标对象,零表示相等,正数表示大于。
Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
本对象与参数进行对比。返回为负表示本对象小于目标对象,零表示相等,正数表示大于。
Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
Comparator泛型接口
int StudentComparator.
compare(Student o1, Student o2)
返回值约定同 Comparable 泛型接口。
当一个类没有实现Comparable接口而又希望对它排序时,可以用Comparator。
超实用的灵活排序实现代码.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Student implements Comparable<Student> {
public int getScore() {
return score;
}
int score;
int number;
public Student(int a, int b) {
number = a;
score = b;
}
@Override
public int compareTo(Student o) {
return (score < o.score ? -1 : (score == o.score ? 0 : 1));
}
@Override
public String toString() {
return "学号number:" + number;
}
@Override
public boolean equals(Object o) {
return o instanceof Student && score == ((Student) o).score;
}
}
class StudentComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return (o1.score < o2.score ? -1 : (o1.score == o2.score ? 0 : 1));
}
}
class StudentComparator2 implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return Double.compare(o1.score, o2.score);
}
}
public class SortDemo {
static List<Student> getData() {
List<Student> list = new ArrayList<>();
list.add(new Student(1, 95));
list.add(new Student(2, 97));
list.add(new Student(3, 96));
return list;
}
public static void main(String[] args) {
// 1. Comparable 接口排序
List<Student> list = getData();
Collections.sort(list);
System.out.println(list);
// 2. 自定义 StudentComparator 排序
list = getData();
Collections.sort(list, new StudentComparator());
System.out.println(list);
// 3. 自定义 StudentComparator2 中 调用 Double.compare
list = getData();
Collections.sort(list, new StudentComparator2());
System.out.println(list);
// 4. lambda 排序
list = getData();
Collections.sort(list, (a, b) -> Double.compare(a.score, b.score));
System.out.println(list);
// 5. 再简洁一点
list = getData();
Collections.sort(list, Comparator.comparingDouble(Student::getScore));
System.out.println(list);
// 6. 简洁的逆序
list = getData();
Collections.sort(list, Comparator.comparingDouble(Student::getScore).reversed());
System.out.println(list);
}
}
/*
[学号number:1, 学号number:3, 学号number:2]
[学号number:1, 学号number:3, 学号number:2]
[学号number:1, 学号number:3, 学号number:2]
[学号number:1, 学号number:3, 学号number:2]
[学号number:1, 学号number:3, 学号number:2]
[学号number:2, 学号number:3, 学号number:1]
*/
<Object> Comparator<Object> java.util.Collections.
reverseOrder()
返回一个comparator,它的规则是自然顺序的倒序。自然顺序与类继承的Comparable接口实现有关。通常用于List的从大到小排列。
返回一个comparator,它的规则是自然顺序的倒序。自然顺序与类继承的Comparable接口实现有关。通常用于List的从大到小排列。
equals()重写
equals(Object obj)是Object类的方法,实现见下:
//Object.java
public boolean equals(Object obj) {
return (this == obj);
}
对于自定义的类,可重写此方法达到想要的目的。可参照JDK中String类的equals方法:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
如果一个类已经有了compareTo()方法,就可以这么写:
@Override
public boolean equals(Object obj) {
return compareTo((E)obj)==0;
}
package com.likeyichu;
import java.lang.reflect.Field;
public class MyEqualsUtil {
public static int hashCode(Object obj){
int x=0;
try{
//only consider public Fields
for(Field field:obj.getClass().getFields())
x+=field.get(obj).hashCode();
}catch(Exception e){
}
//if exception happens,the code after catch block still works.
return x;
}
public static boolean equals(Object a,Object b){
if(a==b)
return true;
try{
if(a.getClass()!=b.getClass())
return false;
//consider all fields including the private
for(Field field:a.getClass().getDeclaredFields()){
field.setAccessible(true);
if(!field.get(a).equals(field.get(b)))
return false;
}//for
}catch(Exception e){
return false;
}
return true;
}
}
然后,对于自定义的类,就可以这样调:
public class BWGRecheckRequest {
//'online' or 'h5' or 'app'
public String source;
//'ip' or 'clientid'
public String keyType;
//accurate ip or clientid
public String theKey;
//flight,hotel,tuan,and so on
public String channel;
@Override
public int hashCode() {
return MyEqualsUtil.hashCode(this);
}
@Override
public boolean equals(Object obj) {
return MyEqualsUtil.equals(this, obj);
}
}