简介
在Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。
Java中的对象,正常情况下,只能进行比较:== 或 != 。不能使用 > 或 < 的。但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。
如何实现?使用两个接口中的任何一个:Comparable 或 Comparator
Java实现对象排序的方式有两种:
- 自然排序:
java.lang.Comparable
- 定制排序:
java.util.Comparator
自然排序Comparable
对象之间要想排序,首先要实现Comparable接口。Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序。
实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即 通过 compareTo(Object obj) 方法的返回值来比较大小。(以下规则是按照从小到大排序的,如果要从大到小即返回相反的)
- 如果当前对象this大 于形参对象obj,则返回正整数
- 如果当前对象this小于形参对象obj,则返回负整数
- 如果当前对象this等于形参对象obj,则返回零。
实现Comparable接口的对象列表(和数组)可以通过Collections.sort
或Arrays.sort
进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
对于类 C 的每一个 e1 和 e2 来说,当且仅当 e1.compareTo(e2) == 0 与 e1.equals(e2) 具有相同的 boolean 值时,类 C 的自然排序才叫做与 equals 一致。建议(虽然不是必需的)最好使自然排序与 equals 一致。
Comparable 的典型实现:(默认都是从小到大排列的)
- String:按照字符串中字符的Unicode值进行比较
- Character:按照字符的Unicode值来进行比较
- 数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值 大小进行比较
- Boolean:true 对应的包装类实例大于 false 对应的包装类实例 Date、Time等:后面的日期时间比前面的日期时间大


1 2 3 4 5 6 7 8 9
| @Test public void test1() { String[] arr = new String[]{"AA", "CC", "KK", "MM", "GG", "JJ", "DD"}; Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
|
查看String源码得知,实现了Comparable接口,重写了compareTo方法


我们自己来编写一个Goods商品类,来实现自然排序。

Double类中的compare方法。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| import com.sun.tools.corba.se.idl.constExpr.Or;
public class Goods implements Comparable<Goods> {
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 + '}'; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
@Override public int compareTo(Goods o) { if (this.price > o.price) { return 1; } else if (this.price < o.price) { return -1; } else { return this.name.compareTo(o.name); }
} }
|

1 2 3 4 5 6 7 8 9 10 11 12
| @Test public void test2() { Goods[] goods = new Goods[5]; goods[0] = new Goods("Mi", 44); goods[1] = new Goods("Dell", 65); goods[2] = new Goods("Lenovo", 55); goods[3] = new Goods("Apple", 999); goods[4] = new Goods("CF", 65);
Arrays.sort(goods); Arrays.stream(goods).forEach(System.out::println); }
|
定制排序Comparator
当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码, 或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那 么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排 序的比较。
重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
- 如果方法返 回正整数,则表示o1大于o2;
- 如果返回0,表示相等;
- 返回负整数,表示 o1小于o2。
可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort), 从而允许在排序顺序上实现精确控制。
还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的 顺序,或者为那些没有自然顺序的对象 collection 提供排序。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Test public void test3() { String[] arr = new String[]{"AA", "CC", "KK", "MM", "GG", "JJ", "DD"}; Arrays.sort(arr, new Comparator<String>() { @Override public int compare(String o1, String o2) { return -o1.compareTo(o2); } }); System.out.println(Arrays.toString(arr));
Arrays.sort(arr,(o1, o2) -> o1.compareTo(o2)); Arrays.asList(arr).stream().forEach(System.out::println);
Arrays.sort(arr,String::compareTo); System.out.println(Arrays.toString(arr)); }
|
