对集合中的元素排序,我们可以使用Collections工具类如:
List list1 = new ArrayList<>();
list1.add(2);
list1.add(1);
list1.add(5);
System.out.println(list1);
Collections.sort(list1);
System.out.println(list1);
// 输出
[2, 1, 5]
[1, 2, 5]
为什么是升序排序?怎么改为降序呢?如果想要对一个学生的属性进行排序?如:
class Student {
public String name;
public int age;
public double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return 'Student{' +
'name='' + name + ''' +
', age=' + age +
', score=' + score +
'}';
}
}
public class TestDemo {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(new Student('张三', 12, 70));
list.add(new Student('李四', 18, 81));
list.add(new Student('王五', 21, 93));
System.out.println(list);
// 显然这里是不行的
Collections.sort(list);
System.out.println(list);
}
}
显然这里是不行的,谁知道这是按学生的哪个属性排序,那么怎么去自定义排序的方式呢?
这里为什么是升序排序?
先说结论:Integer包装类实现了Comparable接口,重写了compareTo方法,而compareTo方法的返回值影响排序是升序还是降序
我们来看看JDK8的源码
Collections.sort源码:我们这里的List保存的是Integer类型,源码这里可知Integer一定实现了Comparable接口我们看看Integer包装类确实继承了Comparable接口
再看看Comparable接口,接口中只有一个compareTo的抽象方法,返回一个int类型的值Integer包装类中重写compareTo方法,compareTo方法中调用了compare方法compare方法返回的0或者-1或者1取决于传入两数的大小,在x
Comparable接口中的compareTo方法和排序有什么关系?
sort传入null这里圈起来的都为null点进这里继续终于破案了,我们的list一路传递到这里,在这里调用了刚才的compareTo方法,这里就是排序的部分代码,compareTo方法的返回值影响排序是升序还是降序如果前一个数大于后一个数,返回交换顺序,升序排序。
怎么改为降序呢?
由上边的分析我们可知只需修改compareTo的比较方式就行,但是这里的compareTo方法是Integer包装类中重写的,我们没办法修改。那让我们再看看另外一个sort的重载方法,发现还有第二个参数
Comparator接口中有一个compare的抽象方法,也是返回一个int类型
Comparator接口中的compare方法和排序有什么关系?
这次传入的第二个参数不为null,进入这里最后同compareTo一样,在最后compare比较返回值影响排序的结果
实现Comparator接口,改为降序排序
不会写没关系,直接复制刚才Integer里的代码,修改(x
class MyCompare implements Comparator {
@Override
public int compare(Integer x, Integer y) {
return (x > y) ? -1 : ((x == y) ? 0 : 1);
}
}
public class TestDemo {
public static void main(String[] args) {
List list1 = new ArrayList<>();
list1.add(2);
list1.add(1);
list1.add(5);
System.out.println(list1);
MyCompare myCompare = new MyCompare();
Collections.sort(list1, myCompare);
System.out.println(list1);
}
}
// 输出:
[2, 1, 5]
[5, 2, 1]
我们还可以将compare方法修改为这样,这是相同的意思,而且更简便。
class MyCompare implements Comparator {
@Override
public int compare(Integer x, Integer y) {
return y - x;
}
}
以下几种方式都可以实现降序排序,为方便记忆,o1作为第一个参数,o2作为第二个参数,o2-o1降序(,o1-o2升序
Collections.sort(list1, new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
// lambda 表达式
Collections.sort(list1, (Integer o1, Integer o2) -> {return o2 - o1; });
// 简写
Collections.sort(list1, (o2, o1) -> o2 - o1);
// Collections.sort 也是调用了list.sort,所以也可以直接这样写
list1.sort((o2, o1) -> o2 - o1);
对一个学生的属性进行排序
Student类实现Comparable接口
因为Student是我们写的类,那么就可以学这Integer包装类去实现Comparable接口,先看看刚才Integer是怎么写的this.value作为第一个参数,compareTo传入的参数作为第二个参数我们也可以理解为
自己实现
class Student implements Comparable{
public String name;
public int age;
public double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return 'Student{' +
'name='' + name + ''' +
', age=' + age +
', score=' + score +
'}';
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}
public class TestDemo {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(new Student('张三', 12, 70));
list.add(new Student('李四', 21, 81));
list.add(new Student('王五', 18, 93));
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
}
// 运行结果,按年龄升序排序
[Student{name='张三', age=12, score=70.0}, Student{name='李四', age=21, score=81.0}, Student{name='王五', age=18, score=93.0}]
[Student{name='张三', age=12, score=70.0}, Student{name='王五', age=18, score=93.0}, Student{name='李四', age=21, score=81.0}]
这里我们看出来要修改比较的东西时,就可能要重新修改重写的方法,而正常情况下Student是封装好的,所以这个局限性就比较大,这才有了Comparator接口,也称之为比较器;而刚才在创建类时就实现Comparable接口定义的排序方式称自然排序或内部排序。
基于Comparator接口,自定义比较器
public class TestDemo {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(new Student('张三', 12, 70));
list.add(new Student('李四', 21, 81));
**加粗样式** list.add(new Student('王五', 18, 93));
System.out.println(list);
// 自然排序
Collections.sort(list);
System.out.println(list);
// 自定义比较器
Collections.sort(list, (o1, o2) -> (int) (o2.score - o1.score));
System.out.println(list);
}
}
总结
Java集合框架Collections工具类中的sort方法可以对集合中元素排序,前提是对象是可比较的,我们可以通过创建对象时实现Comparable接口,或者在调用sort方法时将自己实现的Comparator接口作为参数传入。
Comparable接口和Comparator接口比较
Comparable接口在创建类时要手动实现并重写compareTo方法,一旦实现,每次用该类都有指定的顺序,属于内部顺序。如果要更换比较的方式,则要修改compareTo方法,侵入性强。Comparator接口实现后作为参数传入Collections.sort。每次使用都要确定比较器,比较方式在实现比较器的时候重写compare方法确定,侵入性较弱。
文章为作者独立观点,不代表股票交易接口观点