简介
在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等:后面的日期时间比前面的日期时间大


| 12
 3
 4
 5
 6
 7
 8
 9
 
 | @Testpublic 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方法。

| 12
 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);
 }
 
 
 
 }
 }
 
 | 

| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | @Testpublic 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 提供排序。

| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | @Testpublic 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));
 }
 
 | 
