java.lang.Comparable接口和java.util.Comparator接口的区别

Comparable简介

Comparable接口是排序接口,该接口只有一个抽象方法compareTo(),实现该接口的类必须重写该方法。实现该类的接口有String、所有包装类等。所有实现该接口的类都可以使用Arrays.sort和Collections.sort自动排序。以下是Comparable接口的源码。

public interface Comparable<T> {
    public int compareTo(T o);
}

再看一下String类中对compareTo方法的重写

    public int compareTo(String anotherString) {//该方法按照字典顺序比较两个字符串是否相等,基于字符串各个字符的unicode码。
        int len1 = value.length;//len1为引用该方法字符串的长度,也就是源字符串的长度
        int len2 = anotherString.value.length;//len2为目标字符串的长度
        int lim = Math.min(len1, len2);//lim为两个字符串长度中较小的那一个
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {//循环lim次,比较两个字符串同位置的字符的unicode码
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {//如果两个字符的unicode码不相等,则返回c1-c2,也就是说当返回一个负数时表示,两个字符串第一次出现不同字符时,源字符串在该位置的字符unicode码小于目标函数该位置上字符的unicode码,比如源字符串abc目标字符串acd,
                return c1 - c2;//char类型在做运算时自动转换为int类型
            }
            k++;
        }
        return len1 - len2;//当循环走完都没有发现两个位置上有不同的字符,说明有三种情况发生1)返回值为0表示两个字符串的长度一样并且每个位置的字符都相同,则这两个字符串一样2)返回值为负数,表示源字符串长度比目标字符串长度小,并且前几位字符都一样,比如源字符串为abc目标字符出味adcd。3)和第二种情况相反,比如源字符串为abcd目标字符串为abc。
    }

Comparatpr接口简介

Comparator是比较接口,需要我们自己定义比较的规则

@FunctionalInterface//函数式接口的注解
public interface Comparator<T> {
    int compare(T o1, T o2);

    boolean equals(Object obj);//这里发现一个问题,Comparator接口是一个函数式接口,按道理只能定义一个抽象方法,声明两个抽象方法编译器会报错。这里特意做了实验,发现只要是声明了和Object类中的方法相同方法签名的抽象方法,就可以通过编译,并且不需要重写。
......省略其他默认方法。
}

注意:1.若一个类实现Comparator接口一定要重写compare方法

        2.int compare(T o1,T o2)是比较比较o1和o2在你自己定义的规则下的大小,返回负数说明o1小于o2,返回零说明二者相等,返回正数说明o1大于o2;

Comparable和Comparator区别比较

如果我们需要比较一个类的多个实例,可以实现Comparable接口,实现该接口后表明这个类的对象是可比较的,但是需要在该类中重写CompareTo(T o)方法,这是在内部实现,所以Comparable又被称为内部比较器。而使用Comparator接口的好处就是不需要修改该类的源代码,只需要创建一个比较器来比较该类的实例。还可以用Lambda表达式使代码简单易懂。下面通过一个例子比较二者的区别

使用比较器

public class ComparatorDemo {
	public static void main(String[] args) {
		List<Person> list = new ArrayList<>();
		list.add(new Person("西门吹雪","nan",18));
		list.add(new Person("陆小凤","女",16));
		list.add(new Person("红","男",20));
		list.add(new Person("阿飞","男",12));
		//用比较器根据年龄排序
		Collections.sort(list, (p1,p2)->p1.getAge()-p2.getAge());
		for(Person p:list) {
			System.out.println(p.getName());
		}
	}
}
public class Person {
	private String name;
	private String gender;
	private int age;
	public Person(String name, String gender, int age) {
		super();
		this.name = name;
		this.gender = gender;
		this.age = age;
	}
//省略get和set方法
}

实现Comparable接口

public class ComparableDemo {
	public static void main(String[] args) {
		List<Pelpoe> list = new ArrayList<>();
		list.add(new Pelpoe("西门吹雪","nan",18));
		list.add(new Pelpoe("陆小凤","女",16));
		list.add(new Pelpoe("红","男",20));
		list.add(new Pelpoe("阿飞","男",12));
		Collections.sort(list);
		for(Pelpoe p:list) {
			System.out.println(p.getName());
		}
	}
}
public class Pelpoe implements Comparable<Pelpoe>{//此处如果不加泛型,重写CompareTo方法是能传Object类型
	private String name;
	private String gender;
	private int age;
	public Pelpoe(String name, String gender, int age) {
		super();
		this.name = name;
		this.gender = gender;
		this.age = age;
	}
	
	@Override
	public int compareTo(Pelpoe p) {
		return this.getAge()-p.getAge();
	}
//省略get和set方法
}
现在我想添加业务,要求根据名字的长度排序,比较器只要添加一句代码
Collections.sort(list,(p1,p2)->p1.getName().length()-p2.getName().length());

而第二种方法我必须在pelpoe中修改CompareTo()方法,而且不能重载该方法,也就是说pelpoe对象要么根据名字要么根据年龄排序。

	public int compareTo(Pelpoe p) {
		return this.getName().length()-p.getName().length();
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值