JAVA常用类——Java 比较器Comparable 和 Comparator

本文介绍了Java中两种对象排序方式:自然排序(Comparable接口)和定制排序(Comparator接口)。通过示例详细讲解了Comparable接口的使用,包括String类的compareTo()方法以及自定义类如何实现Comparable接口进行排序。同时,阐述了Comparator接口的应用,展示了如何自定义比较器进行定制排序,以及如何在自定义类中使用Comparator进行复杂排序逻辑的实现。

JAVA常用类——Java 比较器

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

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

说明:Java中的对象,正常情况下,只能进行比较: ==或!=。不能使用 〉或〈 ,但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。如何实现?使用两个接口中的任何一个: Comparable或 Comparator

1、自然排序 Comparable

1.1、Comparable 接口的使用

使用代码实例:

String[] str = new String[]{"aa","kk","dd","cc"};
Arrays.sort(str);
System.out.println(Arrays.toString(str));//[aa, cc, dd, kk]

Comparable 接口使用说明

1、像String、包装类等实现了Comparable 接口,重写了Comparable 接口中的 compareTo(T o)方法,给出了比较两个对象大小的方式,默认从小到大排序。

2、重写 compareTo(T o) 规则:

  • 如果当前对象this大于形参对象o,则返回正整数
  • 如果当前对象this小于形参对象o,则返回负整数
  • 如果当前对象this等于形参对象o,则返回零

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

分析:按字典顺序比较两个字符串。 比较基于字符串中每个字符的 Unicode 值。 此String对象表示的字符序列按字典顺序与参数字符串表示的字符序列进行比较。

如果此String对象按字典顺序位于参数字符串之前,则结果为负整数。 如果此String对象按字典顺序跟在参数字符串之后,则结果为正整数。 如果字符串相等,则结果为零; 当equals(Object)方法返回true时, compareTo返回0 。
这是字典排序的定义。 如果两个字符串不同,那么它们要么在对两个字符串都是有效索引的某个索引处具有不同的字符,要么它们的长度不同,或者两者都有。 如果它们在一个或多个索引位置有不同的字符,则令k为最小的此类索引; 则在位置k处的字符具有较小值的字符串(通过使用 < 运算符确定)按字典顺序排在另一个字符串之前。 在这种情况下, compareTo返回两个字符串中位置k处的两个字符值的差——即:
this.charAt(k) - anotherString.charAt(k)

如果没有它们不同的索引位置,则较短的字符串按字典顺序排在较长的字符串之前。 在这种情况下, compareTo返回字符串长度的差值——即:
this.length() - anotherString.length()

参数:
anotherString – 要比较的String 。
返回:
如果参数字符串等于此字符串,则值为0 ; 如果此字符串按字典顺序小于字符串参数,则为小于0的值; 如果此字符串按字典顺序大于字符串参数,则为大于0的值。

1.2、自定义类实现Comparable 自然排序

对于自定义类来说,如果需要排序,可以让自定义类实现 Comparable接口,重写compareTo(T o) 方法,并且在compareTo(T o) 方法中指明如何排序。

自定义类:

package compare;

public class Goods implements Comparable{
    private String name;
    private double price;

    public Goods() {
    }
    
    public Goods(String name, double price) {
        this.name = name;
        this.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 String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

    //重写compareTo方法,并指明排序的方式:先按价格从低到高排序,再按名称从高到低排序
    @Override
    public int compareTo(Object o) {
        //instanceof ,用来测试对象0是否为Goods类的实例
       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("输入类型错误,无法比较");
    }
}

测试代码:

Goods[] goods = new Goods[4];
goods[0] = new Goods("apple",20);
goods[1] = new Goods("xiaomi",17);
goods[2] = new Goods("honor",45);
goods[3] = new Goods("vivo",34);
goods[3] = new Goods("oppo",17);

Arrays.sort(goods);
System.out.println(Arrays.toString(goods));//[Goods{name='xiaomi', price=17.0}, Goods{name='oppo', price=17.0}, Goods{name='apple', price=20.0}, Goods{name='vivo', price=34.0}, Goods{name='honor', price=45.0}]

2、定制排序 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提供排序。

Comparator 接口的使用:

String[] str = new String[]{"aa","kk","dd","cc"};
Arrays.sort(str, new Comparator<String>() {
    @Override
    //从大到小进行排序
    public int compare(String o1, String o2) {
        return -o1.compareTo(o2);
    }
});
System.out.println(Arrays.toString(str));//[kk, dd, cc, aa]

自定义类实现 Comparator 定制排序

Goods[] goods = new Goods[5];
goods[0] = new Goods("apple",20);
goods[1] = new Goods("xiaomi",17);
goods[2] = new Goods("honor",45);
goods[3] = new Goods("vivo",34);
goods[4] = new Goods("oppo",17);

Arrays.sort(goods, new Comparator<Goods>() {
    @Override
    //先按照名称从低到高排序,再按照价格从高到个低排序
    public int compare(Goods o1, Goods o2) {
        if (o1.getName().equals(o2.getName())){
            //compare默认是从低到高排序
            return -Double.compare(o1.getPrice(),o2.getPrice());
        }else {
           return o1.getName().compareTo(o2.getName());
        }
    }
});
System.out.println(Arrays.toString(goods));//[Goods{name='apple', price=20.0}, Goods{name='honor', price=45.0}, Goods{name='oppo', price=17.0}, Goods{name='vivo', price=34.0}, Goods{name='xiaomi', price=17.0}]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万里顾—程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值