java接口比较器Comparator与Comparable

前言

Java中提供了两个用于比较的接口Comparable 和 Comparator,当涉及到排序等需要比较两个对象的时候,就需要使用比较器。

java.lang.Comparable接口定义:

package java.lang;
public interface Comparable<T> {
   
    public int compareTo(T o);
}

java.util.Comparator定义:

@FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2);
    ......
}

一、Comparator与Comparable的区别

两者都是做比较排序的接口,相对来说我们可以把Comparable理解为内部比较器,Comparator理解为外部比较器。

再同时实现了这两种比较器的时候,Comparator 的优先级较高

Comparable:需要进行排序的实体去实现此接口,需要修改源码,耦合度较高。他是一种思想

Comparator:新建java类去实现此接口,不需要修改源码,耦合度相对不高。他是一种逻辑结构

这里提到的耦合度并不是说哪个好哪个不好,存在即是真理,只是相对而言。举例:开发过程中突然有一个类涉及到排序相关的业务,考虑到尽量不修改原先排序代码的原则,可以考虑去实现Comparator接口。再举例:一个原本就用来做排序的类,有很明显的排序关系像字母顺序、数值排序,再创建初期我们就要考虑去实现Comparable。

二、Comparable

比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

参数: o - 要比较的对象。

返回:负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。

抛出:ClassCastException - 如果指定对象的类型不允许它与此对象进行比较

int compareTo(T o)

三、Comparator

o1 - 要比较的第一个对象

o2 - 要比较的第二个对象

返回:比较它的两个参数的顺序。如果第一个参数大就返回正数,相等返回0,否则返回负数

抛出:NullPointerException - 如果参数为null并且此比较器不允许空参数

抛出:ClassCastException - 如果参数的类型阻止它们被这个比较器比较。

int compare(T o1, T o2)
1、提取基础键比较器

如果指定的函数也是可序列化的,则返回的比较器是可序列化的。
类型参数:
T - 要比较的元素类型
U- Comparable排序键的类型
参数:keyExtractor- 用于提取Comparable排序键的函数
抛出:NullPointerException - 如果参数为null

static <T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor)
static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor)
static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor)
static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)
//keyComparator是针对于keyExtractor返回值的比较器
static <T,U> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)

案例1

List<Person> integerLis t= new ArrayList<>();
integerList.add(new Person("a"));
integerList.add(new Person("g"));
integerList.add(new Person("B"));
integerList.add(new Person("b"));
integerList.add(new Person("G"));
integerList.add(new Person("A"));
	
Comparator<Person> comparator = Comparator.comparing(Person::getName);
Collections.sort(integerList,comparator);
System.out.println(integerList);
//[Person{name=A}, Person{name=B}, Person{name=G}, Person{name=a}, Person{name=b}, Person{name=g}]

案例2

List<Person> integerList = new ArrayList<>();
integerList.add(new Person("a"));
integerList.add(new Person("g"));
integerList.add(new Person("B"));
integerList.add(new Person("b"));
integerList.add(new Person("G"));
integerList.add(new Person("A"));
//不使用String默认的构造器。
Comparator<Person> comparator = Comparator.comparing(Person::getName,String.CASE_INSENSITIVE_ORDER);
Collections.sort(integerList,comparator);
System.out.println(integerList);
//[Person{name=a}, Person{name=A}, Person{name=B}, Person{name=b}, Person{name=g}, Person{name=G}]
2、自然顺序比较对象的比较器

注意不能为空

static <T extends Comparable<? super T>> Comparator<T> naturalOrder()

案例

List<Integer> integerList = new ArrayList<>();
integerList.add(1);
integerList.add(123);
integerList.add(45);
integerList.add(68);
integerList.add(67);
		
Collections.sort(integerList,Comparator.naturalOrder());
System.out.println(integerList);
//[1, 45, 67, 68, 123]
3、空值比较器
//返回一个空值友好的比较器,它被认为null小于非null。
static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator)

//返回一个空值友好的比较器,它被认为null大于非null。
static <T> Comparator<T> nullsLast(Comparator<? super T> comparator)

案例

List<Integer> integerList = new ArrayList<>();
integerList.add(1);
integerList.add(123);
integerList.add(45);
integerList.add(68);
integerList.add(67);
integerList.add(null);

Collections.sort(integerList,Comparator.nullsFirst(Comparator.naturalOrder()));
System.out.println(integerList);
[null, 1, 45, 67, 68, 123]

注意这个Comparator.nullsFirst他的判空是针对List中的元素,如下

List<Person> integerList = new ArrayList<>();
integerList.add(new Person("a"));
integerList.add(new Person("g"));
integerList.add(new Person("B"));
integerList.add(new Person("b"));
integerList.add(new Person(null));
integerList.add(new Person("A"));

integerList.sort(Comparator.nullsLast(Comparator.comparing(Person::getName)));//空指针异常
System.out.println(integerList);

因为nullsLast的判空是在Person上,而在其name属性上,我们可以这样写

Comparator<Person> comparator = Comparator.comparing(Person::getName,Comparator.nullsLast(String::compareTo));
integerList.sort(comparator);
4、比较器的反向排序
//返回一个比较器,它强加了自然顺序的反转
static <T extends Comparable<? super T>> Comparator<T> reverseOrder()
//将比较器反转
default Comparator<T> reversed()

案例

List<Integer> integerList = new ArrayList<>();
integerList.add(1);
integerList.add(123);
integerList.add(45);
integerList.add(68);
integerList.add(67);
Collections.sort(integerList,Comparator.reverseOrder());
System.out.println(integerList);
[123, 68, 67, 45, 1]
5、二次排序
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor)
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor)
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor)

//他们2个不同在于,第一个使用的是词典顺序比较器,而第二个使用的是我们自定义的比较器
default <U extends Comparable<? super U>>Comparator<T> thenComparing(Function<? super T,? extends U> keyExtractor)
default Comparator<T> thenComparing(Comparator<? super T> other)

default <U> Comparator<T> thenComparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)


案例1

List<Person> integerList = new ArrayList<>();
integerList.add(new Person("aaa"));
integerList.add(new Person("gggg"));
integerList.add(new Person("Bb"));
integerList.add(new Person("bb"));
integerList.add(new Person("Gggg"));
integerList.add(new Person("Aaa"));

Comparator<String> comparatorString = Comparator.comparing(String::length).thenComparing(String.CASE_INSENSITIVE_ORDER);
Comparator<Person> comparator = Comparator.comparing(Person::getName,comparatorString);

Collections.sort(integerList,comparator);
System.out.println(integerList);
[Person{name=Bb}, Person{name=bb}, Person{name=aaa}, Person{name=Aaa}, Person{name=gggg}, Person{name=Gggg}]

案例2

List<Person> integerList = newArrayList<>();
integerList.add(new Person("a",1));
integerList.add(new Person("g",1));
integerList.add(new Person("b",1));
integerList.add(new Person("b",2));
integerList.add(new Person("g",2));
integerList.add(new Person("a",2));

Comparator<Person> comparator = Comparator.comparing(Person::getName).thenComparing(Person::getAge);

Collections.sort(integerList,comparator);
System.out.println(integerList);

[Person{name='a', age='1'}, Person{name='a', age='2'},
 Person{name='b', age='1'}, Person{name='b', age='2'}, 
Person{name='g', age='1'}, Person{name='g', age='2'}]


案例3

List<Person> integerList = new ArrayList<>();
integerList.add(new Person("a",1));
integerList.add(new Person("g",1));
integerList.add(new Person("b",1));
integerList.add(new Person("b",2));
integerList.add(new Person("g",2));
integerList.add(new Person("a",2));
	
Comparator<Person> comparator = Comparator.comparing(Person::getName).thenComparing(Person::getAge,Comparator.reverseOrder());

Collections.sort(integerList,comparator);
System.out.println(integerList);
//[Person{name='a', age='2'}, Person{name='a', age='1'}, 
//Person{name='b', age='2'}, Person{name='b', age='1'},
//Person{name='g', age='2'}, Person{name='g', age='1'}]


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值