Saul's blog Saul's blog
首页
后端
分布式
前端
更多
分类
标签
归档
友情链接
关于
GitHub (opens new window)

Saul.J.Wu

立身之本,不在高低。
首页
后端
分布式
前端
更多
分类
标签
归档
友情链接
关于
GitHub (opens new window)
  • Java入门基础

  • Java核心基础

    • 多线程

    • Java常用类

      • 字符串相关的类
      • JDK8之前日期时间API
      • JDK8中新日期时间API
      • Java比较器
        • Comparable接口
          • 特性
          • 实现
        • Comparator接口
          • 特性
          • 实现
        • 总结
      • 其他类
      • Java随机数
    • 枚举类与注解

    • Java集合

    • 数据结构与算法

    • 泛型

    • IO流

    • 网络编程

    • 反射

    • 函数式编程

  • 设计模式

  • Web开发

  • SpringBoot

  • 微服务

  • Elasticsearch

  • 运维

  • 后端
  • Java核心基础
  • Java常用类
SaulJWu
2020-12-23

Java比较器

image-20201223232740652

正常情况下,对象只能进行比较==或!=,不能使用大于或小于,但是在Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。

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

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

# Comparable接口

# 特性

方式一:自然排序:java.lang.Comparable

  • Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序。
  • 实现Comparable 的类必须实现compareTo(Object obj) 方法,两个对象即通过compareTo(Object obj) 方法的返回值来比较大小。
    • 如果当前对象this大于形参对象obj,则返回正整数,
    • 如果当前对象this小于形参对象obj,则返回负整数,
    • 如果当前对象this等于形参对象obj,则返回零。
  • 实现Comparable接口的对象列表(和数组)可以通过Collections.sort 或Arrays.sort进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
  • 对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(Object obj)方法。

# 实现

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

  • String:按照字符串中字符的Unicode值进行比较
  • Character:按照字符的Unicode值来进行比较
  • 数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值大小进行比较
  • Boolean:true 对应的包装类实例大于false 对应的包装类实例
  • Date、Time等:后面的日期时间比前面的日期时间大

示例1

/**
 * @author Saul.J.Wu
 * @date 2020/12/23
 */
public class Goods implements Comparable {

    private String name;

    private double 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;
    }

    public Goods(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public Goods() {
    }

    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

    @Override
    public int compareTo(Object o) {
        //return Double.compare(this.price, goods.price);
        if (o instanceof Goods) {
            Goods goods = (Goods) o;
            if (this.price > goods.price) {
                return 1;
            } else if (this.price < goods.price) {
                return -1;
            }

            return 0;
        }
        throw new RuntimeException("两种类型不一致");
    }
}
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
54
55
56
57
58
@Test
public void test1() {
    Goods[] arr = new Goods[4];
    arr[0] = new Goods("商品A", 133);
    arr[1] = new Goods("商品B", 53);
    arr[2] = new Goods("商品C", 27);
    arr[3] = new Goods("商品D", 103);
    Arrays.sort(arr);
    System.out.println(Arrays.toString(arr));
}
1
2
3
4
5
6
7
8
9
10

输出结果:

[Goods{name='商品C', price=27.0}, Goods{name='商品B', price=53.0}, Goods{name='商品D', price=103.0}, Goods{name='商品A', price=133.0}]
1

如果需要名字做次序,在价格相等时,做业务逻辑判断,高到低还是低到高均可灵活运用。

@Override
    public int compareTo(Object o) {

        if (o instanceof Goods) {
            Goods goods = (Goods) o;
//            return Double.compare(this.price, goods.price);
            if (this.price > goods.price) {
                return 1;
            } else if (this.price < goods.price) {
                return -1;
            }
            //低到高
            return this.name.compareTo(goods.name);
            //高到低
//            return -this.name.compareTo(goods.name);
        }
        throw new RuntimeException("两种类型不一致");
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# Comparator接口

# 特性

方式二:定制排序:java.util.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 提供排序。

# 实现

  • 创建一个Comparable接口实现类或者使用匿名内部类去实现。
@Test
public void test2() {
    String[] arr = new String[]{"ZZ", "BB", "FF", "KK", "JJ", "GG"};
    //从大到小排序
    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(s2);
            }
            throw new RuntimeException("数据类型不一致");
        }
    });
    System.out.println(Arrays.toString(arr));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void test3() {
    Goods[] arr = new Goods[6];
    arr[0] = new Goods("商品A", 133);
    arr[1] = new Goods("商品B", 53);
    arr[2] = new Goods("商品C", 27);
    arr[3] = new Goods("商品D", 103);
    arr[4] = new Goods("商品G", 103);
    arr[5] = new Goods("商品B", 67);
    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));
}
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

# 总结

Comparable接口和Comparator的对比:

一旦指定,保证Comparable可以在任何位置比较,也可以复用。

如果需要临时性比较,可以选择Comparator

帮我改善此页面 (opens new window)
#Comparable#Comparato
上次更新: 2020/12/24, 05:51:23
JDK8中新日期时间API
其他类

← JDK8中新日期时间API 其他类→

最近更新
01
zabbix学习笔记二
02-28
02
zabbix学习笔记一
02-10
03
Linux访问不了github
12-08
更多文章>
Theme by Vdoing | Copyright © 2020-2022 Saul.J.Wu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式