在日常开发中,很多时候都需要对一些数据进行排序的操作。然而那些数据一般都是放在一个集合中如:Map ,Set ,List 等集合中。他们都提共了一个排序方法 sort(),要对数据排序直接使用这个方法就行,但是要保证集合中的对象是 可比较的。
怎么让一个对象是 可比较的,那就需要该对象实现 Comparable<T> 接口啦。然后重写里面的
compareTo()方法。我们可以看到Java中很多类都是实现类这个接口的 如:Integer,Long 等等。。。
假设我们有一个学生类,默认需要按学生的年龄字段 age 进行排序 代码如下:
public class Student implements Comparable<Student> {
private int id;
private int age;
private String name;
public Student(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
@Override
public int compareTo(Student o) {
//降序
//return o.age - this.age;
//升序
return this.age - o.age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
这里说一下重写的 public int compareTo(Student o){} 这个方法,它返回三种 int 类型的值: 负整数,零 ,正整数。
测试代码:
public static void main(String args[]){
List<Student> list = new ArrayList<>();
list.add(new Student(1,25,"关羽"));
list.add(new Student(2,21,"张飞"));
list.add(new Student(3,18,"刘备"));
list.add(new Student(4,32,"袁绍"));
list.add(new Student(5,36,"赵云"));
list.add(new Student(6,16,"曹操"));
System.out.println("排序前:");
for (Student student : list) {
System.out.println(student.toString());
}
//使用默认排序
Collections.sort(list);
System.out.println("默认排序后:");
for (Student student : list) {
System.out.println(student.toString());
}
}
输出日志:
排序前:
Student{id=1, age=25, name='关羽'}
Student{id=2, age=21, name='张飞'}
Student{id=3, age=18, name='刘备'}
Student{id=4, age=32, name='袁绍'}
Student{id=5, age=36, name='赵云'}
Student{id=6, age=16, name='曹操'}
默认排序后:
Student{id=6, age=16, name='曹操'}
Student{id=3, age=18, name='刘备'}
Student{id=2, age=21, name='张飞'}
Student{id=1, age=25, name='关羽'}
Student{id=4, age=32, name='袁绍'}
Student{id=5, age=36, name='赵云'}
比较器的使用
这个时候需求又来了,默认是用 age 排序,但是有的时候需要用 id 来排序怎么办? 这个时候比较器 :Comparator 就排上用场了。
Comparator 的使用有两种方式:
Collections.sort(list,Comparator<T>);
list.sort(Comparator<T>);
其实主要是看 Comparator 接口的实现,重写里面的 compare 方法。代码如下:
//自定义排序1
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getId() - o2.getId();
}
});
compare(Student o1, Student o2) 方法的返回值跟 Comparable<> 接口中的 compareTo(Student o) 方法 返回值意思相同。另一种写法如下:
//自定义排序2
list.sort(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getId() - o2.getId();
}
});
排序前:
Student{id=1, age=25, name='关羽'}
Student{id=2, age=21, name='张飞'}
Student{id=3, age=18, name='刘备'}
Student{id=4, age=32, name='袁绍'}
Student{id=5, age=36, name='赵云'}
Student{id=6, age=16, name='曹操'}
自定义排序后:
Student{id=1, age=25, name='关羽'}
Student{id=2, age=21, name='张飞'}
Student{id=3, age=18, name='刘备'}
Student{id=4, age=32, name='袁绍'}
Student{id=5, age=36, name='赵云'}
Student{id=6, age=16, name='曹操'}
---------------------
作者:宇智波为什么带土
来源:优快云
原文:https://blog.youkuaiyun.com/qq_23179075/article/details/78753136
版权声明:本文为博主原创文章,转载请附上博文链接!
在1.8的文档中
-
-
-
public static <T> void sort(List<T> list, Comparator<? super T> c)
根据指定的比较器引起的顺序对指定的列表进行排序。 列表中的所有元素必须使用指定的比较器相互比较 (即,c.compare(e1, e2)
不能为ClassCastException
中的任何元素e1
和e2
)。这种保证是稳定的 :等同的元素将不会被排序作为排序的结果。
指定的列表必须是可修改的,但不能调整大小。
实现注意事项:这个实现是一个稳定的,自适应的,迭代的mergeesort,当输入数组被部分排序时,需要比n lg(n)的比较少得多,同时在输入数组被随机排列时提供传统的mergeesort的性能。 如果输入数组几乎被排序,则实现需要大致n个比较。 临时存储要求从几乎排序的输入数组的小常数到随机排序的输入数组的n / 2对象引用。
该实现在其输入数组中具有上升和下降的同等优势,并且可以在同一输入数组的不同部分中利用升序和降序。 它非常适合合并两个或多个排序的数组:简单地连接数组并排序生成的数组。
该实现从Tim Peters的Python列表( TimSort )进行了改编 。 它使用Peter McIlroy的“乐观排序和信息理论复杂性”中的技术,在第四届ACM-SIAM离散算法研讨会论文集,pp 467-474,1993年1月。
该实现将指定的列表转储到数组中,对数组进行排序,并在列表中迭代,从列表中的相应位置重新设置每个元素。 这样可以避免尝试将链表排序到目前为止的n 2 log(n)性能。
参数类型
T
- 列表中对象的类参数
list
- 要排序的列表。c
- 比较器来确定列表的顺序。 一个null
值表示元素的自然排序应该被使用。异常
ClassCastException
- 如果列表包含使用指定的比较器不 相互比较的元素。UnsupportedOperationException
- 如果指定的列表的list-iterator不支持set
操作。IllegalArgumentException
- (可选)如果比较方发现违反Comparator
合同
-
-