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