Java两个比较器
一、自然排序:Comparable接口
-
java.lang.Comparable
-
Comparable 接口强行对实现它的每个类的对象进行整体排序(被称为,类的排序)。
-
重写 compareTo(Object obj) 方法的规则(两个对象通过该方法的返回值来比较大小):
- 如果当前对象this大于形参对象obj,则返回正整数;
- 如果当前对象this小于形参对象obj,则返回负整数;
- 如果当前对象this等于参数对象obj,则返回零。
//String类中对compareTo方法的重写 public int compareTo(String anotherString) { int len1 = value.length; int len2 = anotherString.value.length; int lim = Math.min(len1, len2); char v1[] = value; char v2[] = anotherString.value; int k = 0; while (k < lim) { char c1 = v1[k]; char c2 = v2[k]; if (c1 != c2) { return c1 - c2; } k++; } return len1 - len2; }
-
如果自定义类需要排序,需让自定义类继承 Comparable 接口,重写 compareTo 方法,在其中指定排序方法。
-
实现Comparable接口的对象列表或数组,可以通过 Collections.sort 或 Arrays.sort 进行自动排序。实现此接口的对象可以用作有序映射中的键有序集合中的元素,无需指定比较器。
-
对于类 C 的每一个 e1 和 e2 来说,当且仅当 e1.compareTo(e2) == 0 与 e1.equals(e2) 具有相同的 boolean 值时,类 C 的自然排序才叫做与 equals 一致。建议(虽然不是必需的)最好使自然排序与 equals 一致。
-
自定义类继承接口重写方法的代码举例:
import org.junit.Test; import java.util.Arrays; public class ComparableTest { @Test public void test() { Goods[] arr = new Goods[5]; arr[0] = new Goods("1", 4); arr[1] = new Goods("2", 3); arr[2] = new Goods("3", 2); arr[3] = new Goods("4", 1); arr[4] = new Goods("5", 3); Arrays.sort(arr); System.out.println(Arrays.toString(arr)); } } class Goods implements Comparable{ private String name; private double price; public Goods(String name, double price) { this.name = name; this.price = price; } @Override public String toString() { return "Goods{" + "name='" + name + '\'' + ", price=" + price + '}'; } @Override public int compareTo(Object o) { if (o instanceof Goods) { Goods goods = (Goods)o; if (this.price > goods.price) return 1; else if (this.price < goods.price) return -1; else return -this.name.compareTo(goods.name); } throw new RuntimeException("货物数据输入错误!"); } }
二、定制排序:Compatator
-
当元素的类型没有实现 java.lang.Comparable 接口而又不方便修改代码,或者实现了 java.lang.Comparable 接口的排序顺序不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排序的比较。
-
重写 compare(Object o1, Object o2) 方法(比较 o1 和 o2 的大小):
- 返回正整数,表示 o1 大于 o2;
- 返回 0,表示相等;
- 返回负整数,表示 o1 小于 o2。
-
例子
-
使用String重写的compare方法
import org.junit.Test; import java.util.Arrays; import java.util.Comparator; public class ComparableTest { @Test public void test() { String[] arr = new String[]{ "AA","EE","CC","DD","BB"}; Arrays.sort(arr, new Comparator() { @Override public int compare(Object o1, Object o2) { if (o1 instanceof String && o2 instanceof String) { String s1 = (String)o1; String s2 = (String)o2; return -s1.compareTo(s1); } throw new RuntimeException("输入数据类型不一致!"); } }); System.out.println(Arrays.toString(arr)); } }
-
自定义重写compare方法
package com.exer03; import org.junit.Test; import java.util.Arrays; import java.util.Comparator; public class ComparableTest { @Test public void test() { Goods[] arr = new Goods[5]; arr[0] = new Goods("1", 4); arr[1] = new Goods("2", 3); arr[2] = new Goods("3", 2); arr[3] = new Goods("4", 1); arr[4] = new Goods("1", 3); Arrays.sort(arr, new Comparator() { @Override public int compare(Object o1, Object o2) { if (o1 instanceof Goods && o2 instanceof Goods) { Goods g1 = (Goods)o1; Goods g2 = (Goods)o2; if (g1.getName().equals(g2.getName())) { return -Double.compare(g1.getPrice(), g2.getPrice()); }else{ return g1.getName().compareTo(g2.getName()); } } throw new RuntimeException("输入数据类型不一致!"); } }); System.out.println(Arrays.toString(arr)); } } class Goods { private String name; private double price; public String getName() { return name; } public double getPrice() { return price; } public Goods(String name, double price) { this.name = name; this.price = price; } @Override public String toString() { return "Goods{" + "name='" + name + '\'' + ", price=" + price + '}'; } }
-
三、两者比较
- Comparable 接口的方式一旦一定,保证接口实现类的对象安在任何位置都可以比较大小
- Comparator 属于临时(挽救)性的比较。