java基础-java常用类-java比较器-Comparable接口和Comparator接口

本文深入讲解了Java中对象排序的两种主要方式:自然排序通过实现Comparable接口并重写compareTo方法,以及定制排序通过Comparator接口来定义比较规则。适用于自定义类的排序需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java常用类之java比较器

  • 在java中经常会设计到对象数组的排序问题,那么就涉及到对象之间的比较问题。
  • Java实现对象排序的方式有两种:
    • 自然排序:java.lang.Comparable
    • 定制排序:java.util.Comparator
  1. 方式1:Comparable接口的使用举例:自然排序

    1. 像String,基本数据类型的包装类等实现了Comparable接口,重写了compareTo()方法,给出了比较两个对象大小的方式

      public final class String
          implements java.io.Serializable, Comparable<String>, CharSequence
      {
      	    public int compareTo(String anotherString) {
      	int len1 = count;
      	int len2 = anotherString.count;
      	int n = Math.min(len1, len2);
      	char v1[] = value;
      	char v2[] = anotherString.value;
      	int i = offset;
      	int j = anotherString.offset;
      
      	if (i == j) {
      	    int k = i;
      	    int lim = n + i;
      	    while (k < lim) {
      		char c1 = v1[k];
      		char c2 = v2[k];
      		if (c1 != c2) {
      		    return c1 - c2;
      		}
      		k++;
      	    }
      	} else {
      	    while (n-- != 0) {
      		char c1 = v1[i++];
      		char c2 = v2[j++];
      		if (c1 != c2) {
      		    return c1 - c2;
      		}
      	    }
      	}
      	return len1 - len2;
          }
      }
      
      public final class Integer extends Number implements Comparable<Integer> {
          public int compareTo(Integer anotherInteger) {
      	int thisVal = this.value;
      	int anotherVal = anotherInteger.value;
      	return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
          }
      }
      
    2. 像String,基本数据类型的包装类,重写了compareTo()方法以后,进行了从小到大的排序

    3. 重写compareTo(obj)的规则:
      如果当前对象this大于形参对象obj,则返回正整数
      如果当前对象this小于形参对象obj,则返回负整数
      如果当前对象this等于形参对象obj,则返回零

    4. 对于自定义类需要排序,可以将自定义类实现Comparable接口,重写compareTo()方法
      在compareTo(obj) 方法中指明如何排序

/**
 * 商品类
 * @author jiangl
 * @version 1.0
 * @date 2021/4/20 14:18
 */
public class Goods implements Comparable{

    private String name;
    private int price;

    public Goods() {
    }

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

    @Override
    public int compareTo(Object o) {
        if(o instanceof Goods){
            Goods c = (Goods) o;
            if(this.price > c.getPrice()){
                return 1;
            }else if(this.price < c.getPrice()){
                return -1;
            }else{
                return 0;
            }
        }
        throw new RuntimeException("传入的数据类型不一致!");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}
/**
 * 一、说明java中的对象操作,正常情况下,只能进行比较:== 或 !=。不能使用> 或 <
 *      但是在开发场景中,我们需要对多个对象进行排序,就需要比较对象的大小
 *      解决方法:使用两个接口中的一个:Comparable或Comparator
 * 二、Comparable接口的使用
 *
 * @author jiangl
 * @version 1.0
 * @date 2021/4/20 14:10
 */
public class CompareTest {

    /**
     * Comparable接口的使用举例:
     * 1.像String,包装类等实现了Comparable接口,重写了compareTo()方法,给出了比较两个对象大小的方式
     * 2.像String,包装类,重写了compareTo()方法以后,进行了从小到大的排血
     * 3.重写compareTo(obj)的规则:
     *  如果当前对象this大于形参对象obj,则返回正整数
     *  如果当前对象this小于形参对象obj,则返回负整数
     *  如果当前对象this等于形参对象obj,则返回零
     * 4.对于自定义类需要排序,可以将自定义类实现Comparable接口,重写compareTo()方法
     *   在compareTo(obj) 方法中指明如何排序
     */
    @Test
    public void test(){
        String[] arr = new String[]{"AA","DD","MM","BB","CC","OO","GG"};

        Arrays.sort(arr);

        System.out.println(Arrays.toString(arr));
    }

    @Test
    public void test1(){
        Goods[] arr = new Goods[4];
        arr[0] = new Goods("goods1",34);
        arr[1] = new Goods("goods2",20);
        arr[2] = new Goods("goods3",10);
        arr[3] = new Goods("goods4",59);

        Arrays.sort(arr);

        System.out.println(Arrays.toString(arr));
    }
}

test1的返回结果:

[Goods{name=‘goods3’, price=10}, Goods{name=‘goods2’, price=20}, Goods{name=‘goods1’, price=34}, Goods{name=‘goods4’, price=59}]

  1. 方式2:定制排序:java.util.Comparator
  • 当元素的实现类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前操作,那么可以考虑使用Comparator对象来排序,强行对多个对象进行整体排序的比较。
  • 重写compara(Objeact o1,Object o2)方法,比较o1和o2的大小,如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;如果返回负整数,表示o1小于o2.
  • 可以将comparator传递给sort方法(如,Collections.sort或Arrays.sort),从而允许在排序顺序上实现精确控制
  • 还可以使用Comparator来控制某些数据接口(如有序set或有序映射)的顺序,或者为那些没有自然排序的对象collection提供排序
/**
 * Comparator接口的使用:定制排序
 * 1.背景:
 *  当元素类型没有实现java.lang.Comparable接口而又不方便修改代码
 *  或者实现了Comparable接口但是这个排血规则不符合操作
 *  可以考虑使用Comparator
 * 2.重写compara(Objeact o1,Object o2)方法,比较o1和o2的大小,
 * 如果方法返回正整数,则表示o1大于o2;
 * 如果返回0,表示相等;
 * 如果返回负整数,表示o1小于o2.
 * @author jiangl
 * @version 1.0
 * @date 2021/4/20 14:10
 */
public class ComparatorTest {

    @Test
    public void test1(){
        String[] arr = new String[]{"AB","AA","DB","MA","BB","CC","OO","GG"};

        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
        //按第二个字母排序
        Comparator<String> comparator = new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                if(o1.substring(1,2).compareTo(o2.substring(1,2)) > 0){
                    return 1;
                }else if(o1.substring(1,2).compareTo(o2.substring(1,2)) < 0){
                    return -1;
                }else {
                    return 0;
                }
            }
        };
        Arrays.sort(arr,comparator);
        System.out.println(Arrays.toString(arr));
    }

    @Test
    public void test2(){
        Goods[] arr = new Goods[4];
        arr[0] = new Goods("goods1",34);
        arr[1] = new Goods("goods2",20);
        arr[2] = new Goods("goods3",10);
        arr[3] = new Goods("goods4",59);

        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));

        Comparator<Goods> comparator = new Comparator<Goods>() {
            @Override
            public int compare(Goods o1, Goods o2) {
                return -o1.compareTo(o2);
            }
        };

        Arrays.sort(arr,comparator);
        System.out.println(Arrays.toString(arr));
    }
}

返回结果:

[Goods{name=‘goods3’, price=10}, Goods{name=‘goods2’, price=20}, Goods{name=‘goods1’, price=34}, Goods{name=‘goods4’, price=59}]
[Goods{name=‘goods4’, price=59}, Goods{name=‘goods1’, price=34}, Goods{name=‘goods2’, price=20}, Goods{name=‘goods3’, price=10}]

最后:

Comparable接口与Comparator的使用对比:

Comparable接口一旦定下来,保证Comparable接口实现类的对象在任何位置都可以比较大小

Comparator接口属于临时性的比较。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值