Comparable接口和Comparator接口的使用和区别

2023-04-26 11:16:17

Comparable

Comparable接口在JDK8中的源码:

package java.lang;
import java.util.*;

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

用法:

public class User implements Comparable<User>{
    private Integer id;
    private Integer age;

    public User() {
    }

    public User(Integer id, Integer age) {
        this.id = id;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", age=" + age +
                '}';
    }

    public int compareTo(User o) {
        if(this.age > o.getAge()) {
            return 1;
        }else if(this.age < o.getAge()) {
            return -1;
        }else{
            return 0;
        }
    }
}
public class Test {
    public static void main(String[] args) {
        User user1 = new User(1, 14);
        User user2 = new User(2, 12);
        User user3 = new User(3, 10);
        User[] users = {user1, user2, user3};
        Arrays.sort(users);
        Arrays.stream(users).forEach(System.out::println);
    }
}

int compareTo(T o)

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

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

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

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

Comparator

Comparator接口在JDK8中的源码:

package java.util;

import java.io.Serializable;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
import java.util.Comparators;

public interface Comparator<T> {
	int compare(T o1, T o2);
	//还有很多其他方法...
}

使用:

public class Child {
    private Integer id;
    private Integer age;

    public Child() {
    }

    public Child(Integer id, Integer age) {
        this.id = id;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Child{" +
                "id=" + id +
                ", age=" + age +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        Child child1 = new Child(1, 14);
        Child child2 = new Child(2, 12);
        Child child3 = new Child(3, 10);

        List<Child> list = new ArrayList<>();
        list.add(child1);
        list.add(child2);
        list.add(child3);

        Collections.sort(list, new Comparator<Child>() {
            @Override
            public int compare(Child o1, Child o2) {
                return  o1.getAge() > o2.getAge() ? 1 : (o1.getAge() == o2.getAge() ? 0 : -1);
            }
        });

        // 或者使用JDK8中的Lambda表达式
        //Collections.sort(list, (o1, o2) -> (o1.getAge()-o2.getAge()));

        list.stream().forEach(System.out::println);
    }
}

或者也可以通过实现的方式使用Comparator接口:

import java.util.Comparator;

public class Child implements Comparator<Child> {
    private Integer id;
    private Integer age;

    public Child() {
    }

    public Child(Integer id, Integer age) {
        this.id = id;
        this.age = age;
    }

    @Override
    public int compare(Child o1, Child o2) {
        return o1.getAge() > o2.getAge() ? 1 : (o1.getAge() == o2.getAge() ? 0 : -1);
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Child{" +
                "id=" + id +
                ", age=" + age +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        Child child1 = new Child(1, 14);
        Child child2 = new Child(2, 12);
        Child child3 = new Child(3, 10);

        List<Child> list = new ArrayList<>();
        list.add(child1);
        list.add(child2);
        list.add(child3);
        
        Collections.sort(list, new Child());
        list.stream().forEach(System.out::println);
    }
}

Comparator接口其他默认方法的用法

reversed方法

default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }

这个方法是用来生成一个逆序器,比如我们开始需要得到一个正序的排序序列,然后又想得到一个反转的排序序列,就可以使用该方法。比如:

public class Test {
    public static void main(String[] args) {
        Child child1 = new Child(1, 14);
        Child child2 = new Child(2, 12);
        Child child3 = new Child(5, 10);
        Child child4 = new Child(4, 10);

        List<Child> list = new ArrayList<>();
        list.add(child1);
        list.add(child2);
        list.add(child3);
        list.add(child4);

        Comparator<Child> comparator = Comparator.comparingInt(x -> x.getAge());
        Collections.sort(list, comparator);
        list.stream().forEach(System.out::println);
        Collections.sort(list, comparator.reversed());
        list.stream().forEach(System.out::println);
    }
}

thenComparing

default <U extends Comparable<? super U>> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        return thenComparing(comparing(keyExtractor));
    }

该方法是在原有的比较器上再加入一个比较器,比如先按照年龄排序,年龄相同的在按照id排序。比如:

public class Test {
    public static void main(String[] args) {
        Child child1 = new Child(1, 14);
        Child child2 = new Child(2, 12);
        Child child3 = new Child(5, 10);
        Child child4 = new Child(4, 10);

        List<Child> list = new ArrayList<>();
        list.add(child1);
        list.add(child2);
        list.add(child3);
        list.add(child4);

        Comparator<Child> comparator = Comparator.comparingInt(x -> x.getAge());
        Collections.sort(list, comparator);
        list.stream().forEach(System.out::println);
        System.out.println("-----");
        Collections.sort(list, comparator.thenComparing(x->x.getId()));
        list.stream().forEach(System.out::println);
    }
}

Comparable接口和Comparator接口的区别

  • Comparable接口位于java.lang包下;Comparator位于java.util包下
  • Comparable接口只提供了一个compareTo()方法;Comparator接口不仅提供了compara()方法,还提供了其他默认方法,如reversed()、thenComparing(),使我们可以按照更多的方式进行排序
  • 如果要用Comparable接口,则必须实现这个接口,并重写comparaTo()方法;但是Comparator接口可以在类外部使用,通过将该接口的一个匿名类对象当做参数传递给Collections.sort()方法或者Arrays.sort()方法实现排序。Comparator体现了一种策略模式,即可以不用要把比较方法嵌入到类中,而是可以单独在类外部使用,这样我们就可有不用改变类本身的代码而实现对类对象进行排序。
  • 作者:IT_10-
  • 原文链接:https://blog.csdn.net/IT_10/article/details/104747173
    更新时间:2023-04-26 11:16:17