list的排序
1. 常用类型的排序
一般常用的类型有Integer,Long等包装类型,String,Date,Number类的继承类等。这些常用的类型中有一个共同点就是,都实现了Comparable
接口,并且实现了他的compareTo()
方法
一般常用类型的List的排序就很简单,就按照他的排序规则进行就可以了。
List<Integer> ints = new ArrayList<>();
ints.add(435);
ints.add(757);
ints.add(456)
ints.add(856);
ints.add(446);
ints.add(487);
ints.add(367);
List<Integer> collect = ints.stream().sorted().collect(Collectors.toList());
System.out.println(collect);
Collections.sort(ints);
System.out.println(ints);
ints.sort((o1, o2) -> Integer.compare(o1, o2));
System.out.println(ints);
第一个排序方式是,java8的Stream的一个方法。这个Stream中有很多方法,这种操作类似于SQL语句一般,有选择,过滤,排序等。
第二个排序是Collections
中自带的sort()
方法
这俩个无参方法的调用其实都是针对于实现了Comparable接口
的类来进行的。
这两个方法也有有参的重载方法,需要传入一个lambda表达式
,在Java8之前需要传入一个比较器
在第一个方法中,如果传入的参数没有实现Comparable接口的话,不会报错,但是在执行的时候会报错
在第二个Collections.sort方法中,如果传入的参数没有实现Comparable方法的话,会报错。因为,这个方法的定义上就规定了必须实现了Comparable接口
这个方法的定义中,明确规定了这个<T extends Comparable<? super T>>
第三种方法中,使用了lambda
表达式,非常好用,现在很多list的操作都支持使用lambda
表达式。这些表达式返回的都是数字,分成了三种,小于0,大于0,等于0。
实际上这两种方法中,最终实现的都是靠Arrays.sort(Object[] o)
来完成的。根据方法参数的不同,那么Arrays.sort()
采用的排序方式也不同,在Arrays.sort(Object[] o)
中使用的是TimSort.binarySort()
。
下面是源码
private static <T> void binarySort(T[] a, int lo, int hi, int start, Comparator<? super T> c) {
assert lo <= start && start <= hi;
if (start == lo)
start++;
for ( ; start < hi; start++) {
T pivot = a[start];
// Set left (and right) to the index where a[start] (pivot) belongs
int left = lo;
int right = start;
assert left <= right;
/*
* Invariants:
* pivot >= all in [lo, left).
* pivot < all in [right, start).
*/
while (left < right) {
int mid = (left + right) >>> 1;
if (c.compare(pivot, a[mid]) < 0)
right = mid;
else
left = mid + 1;
}
assert left == right;
/*
* The invariants still hold: pivot >= all in [lo, left) and
* pivot < all in [left, start), so pivot belongs at left. Note
* that if there are elements equal to pivot, left points to the
* first slot after them -- that's why this sort is stable.
* Slide elements over to make room for pivot.
*/
int n = start - left; // The number of elements to move
// Switch is just an optimization for arraycopy in default case
switch (n) {
case 2: a[left + 2] = a[left + 1];
case 1: a[left + 1] = a[left];
break;
default: System.arraycopy(a, left, a, left + 1, n);
}
a[left] = pivot;
}
}
可以看到,针对于lambda
表达式 的处理是,如果返回的小于0,才会交换。
上面是正序的排列,如果有需要排倒序的话,可以排完正序之后reverse()
一下,也可以使用第三种的反一下ints.sort((o1, o2) -> Integer.compare(o2, o1));
2. 对象的排序
一般对象的排序都是,按照其中一个属性来进行排序,或者实现Comparable
接口,自己定义一种排序方式。
2.1 按照对象的某一种属性排序
User.java
package com.self.list;
import java.util.Date;
import java.util.Objects;
public class User{
private Integer id;
private String name;
private Integer age;
private String gender;
private Date birtday;
public User() {
}
public User(Integer id, String name, Integer age, String gender, Date birtday