一、比较器

  在 Java 中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。

  Java 实现对象排序的方式有两种:

自然排序: java.lang.Comparable
定制排序: java.util.Comparator

 

二、自然排序:java.lang.Comparable

  1、概述

    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 一致

 

  2、典型实现

    Compareable 的典型实现:(默认都是从小到大排列的

    •   String:按照字符串中字符的Unicode值进行比较;
    •     Character:按照字符的Unicode值来进行比较;
    •     Booleantrue 对应的包装类实例大于 false 对应的包装类实例;
    •     DateTime等:后面的日期时间比前面的日期时间大;
    •     数值类型对应的包装类以及BigIntegerBigDecimal:按照它们对应的数值大小进行比较;

  3、案例

    Goods 商品类:

 1 public class Goods implements Comparable{
 2 
 3     private String name;
 4     private double price;
 5 
 6     public Goods() {
 7     }
 8 
 9     public Goods(String name, double price) {
10         this.name = name;
11         this.price = price;
12     }
13 
14     public String getName() {
15         return name;
16     }
17 
18     public void setName(String name) {
19         this.name = name;
20     }
21 
22     public double getPrice() {
23         return price;
24     }
25 
26     public void setPrice(double price) {
27         this.price = price;
28     }
29 
30     @Override
31     public String toString() {
32         return "Goods{" +
33                 "name='" + name + '\'' +
34                 ", price=" + price +
35                 '}';
36     }
37 
38     //指明商品比较大小的方式:按照价格从低到高排序,再按照产品名称从高到低排序
39     @Override
40     public int compareTo(Object o) {
41         if(o instanceof Goods){
42             Goods goods = (Goods)o;
43             //方式一:
44             if(this.price > goods.price){
45                 return 1;
46             }else if(this.price < goods.price){
47                 return -1;
48             }else{
49                 //return 0;
50                 return -this.name.compareTo(goods.name);
51             }
52             //方式二:
53             //return Double.compare(this.price,goods.price);
54         }
55         throw new RuntimeException("传入的数据类型不一致!");
56     }
57 }

 

    测试类:

 1 public class ComparableTest {
 2     public static void main(String[] args) {
 3         Goods[] all = new Goods[4];
 4         all[0] = new Goods("《红楼梦》 ", 100);
 5         all[1] = new Goods("《西游记》 ", 80);
 6         all[2] = new Goods("《三国演义》 ", 140);
 7         all[3] = new Goods("《水浒传》 ", 120);
 8         Arrays.sort(all);
 9         System.out.println(Arrays.toString(all));
10     }
11 }

 

三、定制排序:java.util.Comparator

  1、概述

    当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序, 强行对多个对象进行整体排序的比较。
    重写compare(Object o1,Object o2)方法,比较o1o2的大小: 如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示
o1小于o2
    可以将 Comparator 传递给 sort 方法(如 Collections.sort Arrays.sort),从而允许在排序顺序上实现精确控制。
    还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。

  2、方法说明

java.util.Comparator<T>接口:
    抽象方法:int compare(T o1, T o2)

  <T> 是泛型,可以理解成 Object。

  java.util.Comparator接口:

    抽象方法:int compare(Object o1, Object o2)

  说明:这个接口是代表 Java 中比较两个对象的大小标准。而且是一种“定制”比较的标准。

     这个接口中没有规定如何比较两个对象的大小。

     但是规定了:如果认为 o1 大于 o2,那么就返回正整数表示;

           如果认为 o1 小于 o2,那么就返回负整数表示;

           如果认为 o1 等于 o2,那么就返回0表示;

  3、案例

    Demo:定制排序(自定义排序)

 1     @Test
 2     public void test() {
 3         Goods[] all = new Goods[4];
 4         all[0] = new Goods("War and Peace", 100);
 5         all[1] = new Goods("Childhood", 80);
 6         all[2] = new Goods("Scarlet and Black", 140);
 7         all[3] = new Goods("Notre Dame de Paris", 120);
 8         Arrays.sort(all, new Comparator() {
 9             @Override
10             public int compare(Object o1, Object o2) {
11                 Goods g1 = (Goods) o1;
12                 Goods g2 = (Goods) o2;
13                 return g1.getName().compareTo(g2.getName());
14             }
15         });
16         System.out.println(Arrays.toString(all));
17     }

  

  总结:

    Arrays 的 sort 方法有两种:

   (1)void sort(Object[] arr)

       根据元素的自然顺序对指定对象数组按升序进行排序,数组中的所有元素必须实现 Comparable 接口

   (2)void sort(Object[] arr, Comparator c)

       根据“指定比较器”产生的顺序对指定对象数组进行排序,数组中的所有元素都必须是通过“指定比较器”可相互比较的。

 

posted on 2021-03-14 20:09  格物致知_Tony  阅读(131)  评论(0编辑  收藏  举报