likes
comments
collection
share

java集合中的排序方式有哪些?通过Collections工具类中重载的两个sort()方法进行排序,使用Compara

作者站长头像
站长
· 阅读数 62

快速回答

通过Collections工具类中重载的两个sort()方法进行排序,使用Comparable和Comparator接口自定义排序规则。

详解

Collections 工具类提供了重载的两个 sort() 排序方法,分别如下:

2.1 sort(List<T> list)

public static <T extends Comparable<? super T>> void sort(List<T> list){
    list.sort(null);
}

该方法中的泛型 <T> 是 Comparable 接口的子类,即只有实现 Comparable 接口的子类类型的对象,才能进行比较排序。如果是其它类型的数据要进行比较排序,必须继承 Comparable 接口并重写 int compareTo(T o)方法。

将看起来没有实现 Comparable 接口的基本数据类型、String 类型直接放入 Collections.sort(List<T>) 中进行排序没有报错的原因:实际上它们的包装类都实现了 Comparable 接口

public final class Integer extends Number implements Comparable<Integer> {...
public final class Double extends Number implements Comparable<Double> {...
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {...
...

【示例】对 Employee 类对象按 salary 比较项目 进行排序。

List<Employee> list = new ArrayList<>();
list.add(new Employee(1, "张三", 1000));
list.add(new Employee(4, "李四", 9000));
list.add(new Employee(2, "王五", 5000));
list.add(new Employee(3, "赵六", 4000));
Collections.sort(list);

class Employee implements Comparable<Employee> { // 继承Comparable接口
    public int id;
    public String name;
    public int salary;

    public Employee(int id, String name, int salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "\nEmployee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
    }

    // 重写compareTo方法
    @Override
    public int compareTo(Employee o) {
        return this.salary - o.salary;
    }
}

使用Collections.sort(List<T>)方法排序集合时,该方法要求集合元素必须继承 Comparable 接口并且重写 compareTo 方法。这种我们想使用某个功能,而它要求我们修改原来程序代码的现象称为“侵入性”。修改的代码越多,侵入性比较强,越不利于程序的扩展。 所以不建议使用 Collections.sort(List<T>) 这个方法。

2.2 sort(List<T> list, Comparator<? super T> c)

public static <T> void sort(List<T> list, Comparator<? super T> c) {
    list.sort(c);
}

该方法中指定比较方式 Comparator<? super T> c,即 c 必须实现 Comparator<? super T> 接口,重写 compare() 方法指定比较项目。比较项目在类外指定,比较灵活。

  • 重载的 sort(List<T>, Comparator<? super T>) 方法要求传入一个额外的比较器。
  • 该方法不再要求集合元素必须实现 Comparable 接口,并且也不再使用集合元素自身的比较规则排序了,而是根据给定的这个额外的比较器的比较规则对集合元素进行排序。
  • 实际开发中也推荐使用这种方式对集合元素进行排序,若集合元素是自定义的,创建比较器时推荐使用匿名内部类的形式。

(1)自定义一个比较器类然后传入 Collections.sort(List<T>, Comparator<? super T>)中。

Collections.sort(list, new MyComparator());

class MyComparator implements Comparator<Employee>{
    @Override
    public int compare(Employee o1, Employee o2) {
        return o1.salary - o2.salary;
    }
}

(2)采用 匿名内部类/lambda 表达式 的形式(推荐做法)

Collections.sort(list, new Comparator<Employee>() {
    @Override
    public int compare(Employee o1, Employee o2) {
        return o1.salary - o2.salary;
    }
});

Collections.sort(list, (o1, o2) -> o1.salary - o2.salary);

2.3 两个重载的 sort 方法的总结

  1. 对于 Collections.sort(List<T>) 方法 ,因为它要求传入的集合元素(常常是存有类对象的集合)必须实现 Comparable 接口,并且重写其 compareTo(T o) 方法。这样使得对原来的类的修改较多,不利于程序的扩展,所以不建议使用。
  2. 对于Collections.sort(List<T>, Comparator<? super T>) 方法,如果自定义的比较规则需要多次使用,则自定义一个比较器类实现 Comparator 接口、重写 compare 方法即可。如果只需要临时改变比较规则,则可以采用回调方式:匿名内部类的形式重写 Comparator 接口的 compare 方法;或 lambda 表达式。
  3. 第一种方式,在要排序的集合元素/类中继承 Comparable 接口重写 compareTo(T o) 方法。第二种方式,在自定义的比较器类中继承 Comparator 接口重写 compare 方法。
转载自:https://juejin.cn/post/7418507128871403539
评论
请登录