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

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体现了一种策略模式,即可以不用要把比较方法嵌入到类中,而是可以单独在类外部使用,这样我们就可有不用改变类本身的代码而实现对类对象进行排序。
### Java 中 `Comparable` `Comparator` 接口区别及用法 #### 定义与用途 `Comparable<T>` 是一个内置接口,用于定义对象的自然顺序。当类实现此接口时,意味着该类的对象可以按照某种逻辑进行比较。通常情况下,这种逻辑基于某个属性,比如字符串按字母顺序排列或数值类型的大小。 ```java public class Employee implements Comparable<Employee> { private String name; private int age; // Constructor, getters and setters omitted for brevity @Override public int compareTo(Employee other) { return Integer.compare(this.age, other.getAge()); } } ``` 相比之下,`Comparator<T>` 提供了一种灵活的方式来指定额外的排序标准而无需修改原始类的设计。这允许开发者在同一组数据上应用不同的排序策略[^3]。 ```java import java.util.Comparator; public class AgeSorter implements Comparator<Employee> { @Override public int compare(Employee o1, Employee o2) { return o1.getAge() - o2.getAge(); } } ``` #### 使用场景 - **`Comparable`**: 当希望给定类型的实例具有固定的、内在的排序方式时使用。例如,在集合框架中存储自定义对象并期望它们能够自动排序的情况下非常有用。 - **`Comparator`**: 如果需要根据不同条件动态改变排序行为,则更适合采用这种方式。它还可以用来处理那些无法控制其源码的情况下的外部类排序需求。 通过上述两种方法之一来定制化排序机制,可以使程序更加模块化且易于维护。值得注意的是,虽然两者都可以完成相似的任务,但在具体应用场景下各有优劣。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值