Java 比较器 Comparable、Comparator

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()方法。
Java 比较器 Comparable、Comparator
Java 比较器 Comparable、Comparator
Java 比较器 Comparable、Comparator

上一篇:【Java】PriorityQueue 的实现原理


下一篇:PriorityQueue详解