Comparable(自然排序)和Comparator(比较器)的用法(Java)

    在开发场景中,当我们需要对多个对象进行排序,或比较对象的大小,我们可以实现java.lang.Comparablejava.util.Comparator接口。

一、实现Comparable<T>接口,重写 compareTo方法

    Comparable 接口中只提供了一个方法:public int compareTo(T o);。而我们需要重写 compareTo方法:
    如果当前对象this大于对象o,则返回正整数。
    如果当前对象this小于对象o,则返回负整数。
    如果当前对象this等于对象o,则返回0。

class Good implements Comparable<Good>{
	private int price;
	private String name;
	
	public Good(String name,int price) {
		this.price=price;
		this.name=name;
	}

	public int getPrice() {
		return price;
	}

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

	public String getName() {
		return name;
	}

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

	@Override
	public int compareTo(Good o) {
		return this.price-o.price;
	}
	@Override
	public String toString() {
		return "["+name+": "+price+"]";
	}
}
	public static void main(String[] args) {
		Good[] good=new Good[6];
		good[0]=new Good("phone", 3000);
		good[1]=new Good("book", 100);
		good[2]=new Good("earphone", 3000);
		good[3]=new Good("pen", 10);
		good[4]=new Good("computer", 3000);
		good[5]=new Good("bicycle",500);
		Arrays.sort(good);
		System.out.println(Arrays.toString(good));
	}

运行结果:
[[pen: 10], [book: 100], [bicycle: 500], [computer: 3000], [phone: 3000], [earphone: 3000]]

    商品数组的商品原来是乱序的,当调用Arrays.sort(good)时,它会调用compareTo方法,根据其返回值来判断这两个对象的大小,从而进行排序。当然,compareTo方法也可以写成这样:

	@Override
	public int compareTo(Good o) {
		if(this.price > o.price)
			return 1;
		else if(this.price < o.price)
			return -1;
		else
			return 0;
	}

二、实现Comparator<T>接口,重写compare方法

    当元素的类没实现java.lang.Comparable接口而不方便修改代码或者实现了java.lang.Comparable接口,但是其排序的方式不适合所需要的操作,我们可以实现java.util.Comparator接口。另外,Comparator接口的一个好处是将比较排序算法和具体的实体类分离了。
    我们重写 compareTo方法:
    如果对象o1大于对象o2,则返回正整数。
    如果对象o1小于对象o2,则返回负整数。
    如果对象o1等于对象o2,则返回0。
    下面我们将对商品数组按商品价格大小排序,当价格相等,我们按商品的名称排序。

class Good{
	private int price;
	private String name;
	
	public Good(String name,int price) {
		this.price=price;
		this.name=name;
	}

	public int getPrice() {
		return price;
	}

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

	public String getName() {
		return name;
	}

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

	@Override
	public String toString() {
		return "["+name+": "+price+"]";
	}
}
	public static void main(String[] args) {
		Good[] good=new Good[6];
		good[0]=new Good("phone", 3000);
		good[1]=new Good("book", 100);
		good[2]=new Good("earphone", 3000);
		good[3]=new Good("pen", 10);
		good[4]=new Good("computer", 3000);
		good[5]=new Good("bicycle",500);
		Arrays.sort(good, new Comparator<Good>() {
			@Override
			public int compare(Good o1, Good o2) {
				if(o1.getPrice()!=o2.getPrice())
					return o1.getPrice()-o2.getPrice();
				else {
					return o1.getName().compareTo(o2.getName());
				}
			}
		});
		System.out.println(Arrays.toString(good));
	}

运行结果:
[[pen: 10], [book: 100], [bicycle: 500], [computer: 3000], [earphone: 3000], [phone: 3000]]

    可能有的小伙伴会不理解当中的一段代码为什么这样写:

return o1.getName().compareTo(o2.getName());

    其实,像String类包装类等实现了Comparable接口,重写了compareTo方法。大家可以看一下String类的compareTo方法,它采用字典序比较(像上面c<e<p):

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    ...
	public int compareTo(String anotherString) {
        byte v1[] = value;
        byte v2[] = anotherString.value;
        if (coder() == anotherString.coder()) {
            return isLatin1() ? StringLatin1.compareTo(v1, v2)
                              : StringUTF16.compareTo(v1, v2);
        }
        return isLatin1() ? StringLatin1.compareToUTF16(v1, v2)
                          : StringUTF16.compareToLatin1(v1, v2);
     }
	...
}

    最后还要一点,我们上面的排序是按价格从小到大,那如果从大到小,我们只需要做出一些改变就好了

	Arrays.sort(good, new Comparator<Good>() {
			@Override
			public int compare(Good o1, Good o2) {
				if(o1.getPrice()!=o2.getPrice())
					return o2.getPrice()-o1.getPrice();
				else {
					return -o1.getName().compareTo(o2.getName());   //按字典序从大到小
				}
			}
		});

运行结果:
[[phone: 3000], [earphone: 3000], [computer: 3000], [bicycle: 500], [book: 100], [pen: 10]]

三、总结

  1. Comparable 接口,java中大部分类已经实现了Comparable(String,BigDecimal,java.util.Date等),用于比较两个对象大小,十分方便。
  2. Comparator 接口,主要用集合中排序(TreeSet ,TreeMap , Collections.sort()),不同需求的排序方式,直接接口实现,易于功能扩展,不影响原代码。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值