Java比较器
1.自然排序:Comparable
1.1 Comparable接口
public interface Comparable<T>
{
public int compareTo(T o);
}
- 若一个类实现了Comparable接口(即实现 compareTo(Object obj) 方法),则该类支持排序。
-
两个对象通过 compareTo(Object obj) 方法的返回值来比较大小。
如果当前对象this大于形参对象obj,则返回正整数
如果当前对象this小于形参对象obj,则返回负整数
如果当前对象this等于形参对象obj,则返回零 - 实现Comparable接口的对象列表 (或数组) 可以通过 Collections.sort 或 Arrays.sort进行自动排序。
- 实现Comparable接口的对象可以用作 “有序映射(如TreeMap)” 中的键或 “有序集合(TreeSet)” 中的元素,而不需要指定比较器。
1.2 Comparable 的典型实现
注:以下实现默认都是从小到大排列
- String:按照字符串中字符的Unicode值比较
- Character:按照字符的Unicode值比较
- Boolean:true 对应的包装类实例大于 false 对应的包装类实例
- 数值类型对应的包装类、BigInteger、BigDecimal:按照它们对应的数值大小进行比较
- Date、Time等:后面的日期时间比前面的日期时间大
1.String举例
String []arr=new String[]{"aa","C","ad"};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));//[C, aa, ad]
2.Integer举例
Integer []arr=new Integer[] {1,6,4,2};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr)); //[1, 2, 4, 6]
1.3 自定义类实现Comparable接口
// 自定义手机类,拥有name、price属性。
// compareTo方法具体实现:对price进行升序排序,price相同时对name进行降序排序
public class SmartPhone implements Comparable
{
String name;
double price;
public SmartPhone(String name, double price)
{
this.name = name;
this.price = price;
}
@Override
public String toString()
{
return "SmartPhone [name=" + name + ", price=" + price + "]";
}
@Override
public int compareTo(Object o)
{
if(o instanceof SmartPhone)
{
SmartPhone sp=(SmartPhone)o;
if(this.price>sp.price)
return 1;
else if(this.price<sp.price)
return -1;
else//此时说明二者price相同 (然后按照name降序)
{
return -this.name.compareTo(sp.name); //String 本来是升序,-表示将升序转换为降序
}
}
throw new RuntimeException("请传入正确数据类型");
}
}
@Test
public void SmartPhoneTest()
{
SmartPhone []arr=new SmartPhone[5];
arr[0]=new SmartPhone("XiaoMi", 3999);
arr[1]=new SmartPhone("HuaWei", 4999);
arr[2]=new SmartPhone("OPPO" , 3299);
arr[3]=new SmartPhone("OnePlus", 3999);
arr[4]=new SmartPhone("iphone", 4999);
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
// 输出
[
SmartPhone [name=OPPO, price=3299.0],
SmartPhone [name=XiaoMi, price=3999.0],
SmartPhone [name=OnePlus, price=3999.0],
SmartPhone [name=iphone, price=4999.0],
SmartPhone [name=HuaWei, price=4999.0]
]
2.定制排序:Comparator
2.1 Comparator 接口
public interface Comparator<T>
{
int compare(T o1, T o2);
boolean equals(Object obj);
}
- 当元素的类型没有实现java.lang.Comparable接口 或 实现了java.lang.Comparable接口但是排序规则不适合当前的操作。那么可以实现 Comparator 接口进行比较。
-
类实现 Comparator 接口 一定要 实现 compareTo(T o1, T o2) 函数
类实现 Comparator 接口 不一定要 实现 equals(Object obj) 函数。 ( 因为Java中的一切类都是继承于java.lang.Object类。Object类中实现了equals(Object obj)函数,相当于其它所有类也实现了该函数 ) -
两个对象通过 int compare(T o1, T o2) 方法的返回值来比较大小。
如果o1>o2, 则返回正整数
如果o1<o2, 则返回负整数
如果o1==o2,则返回零
2.2 重写compare(T o1,T o2)使String 降序排列
String []arr=new String[]{"aa","C","ad"};
Arrays.sort(arr, new Comparator()
{
@Override
public int compare(Object o1, Object o2)
{
if(o1 instanceof String && o2 instanceof String)
{
String str1=(String)o1;
String str2=(String)o2;
return -str1.compareTo(str2);
}
throw new RuntimeException("请传入正确数据类型");
}
});
System.out.println(Arrays.toString(arr));//[ad, aa, C]
3.Comparable、Comparator区别
- Comparable相当于“内部比较器”,Comparator相当于“外部比较器”。
- Comparable 是排序接口:若一个类实现了 Comparable 接口,就意味着 “该类支持排序”。
Comparator 是比较器: 若需要控制某个类的次序,可以建立一个 “该类的比较器” 来进行排序。
4. 关于Comparable接口的一点说明
为什么使用Arrays排序的对象都要实现Comparable接口。能否直接在类中定义一个 compareTo 方法?
不能。因为 Arrays.sort(Object[] objs ) 内部必须把Object数组里面强制转换为Comparable类型,才可以调用comparaTo()方法。