场景
Bean定义如下,仅有一个类型为Integer
的age
字段。
@NoArgsConstructor
@AllArgsConstructor(staticName = "of")
@Data
public static class Employee {
private Integer age;
}
列表初始化5个元素:
List<Employee> list = new ArrayList<>();
list.add(Employee.of(21));
list.add(Employee.of(22));
list.add(Employee.of(25));
list.add(Employee.of(28));
list.add(Employee.of(23));
排序
使用Collections
中的sort
方法进行排序:
Collections.sort(list, new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
倒序:
Collections.reverse(list);
lambda表达式
JDK8支持lambda表达式,写法更加简洁:
Collections.sort(list, (o1, o2) -> o1.getAge().compareTo(o2.getAge()));
或者使用Comparator
接口:
Collections.sort(list, Comparator.comparing(Employee::getAge));
倒序:
Collections.sort(list, Comparator.comparing(Employee::getAge).reversed());
stream的sorted方法
list.stream().sorted(Comparator.comparing(Employee::getAge));
倒序:
list.stream().sorted(Comparator.comparing(Employee::getAge).reversed());
list自带的sort方法
list.sort(Comparator.comparing(Employee::getAge));
倒序:
list.sort(Comparator.comparing(Employee::getAge).reversed());
null值
假设列表中有age
字段为null:
List<Employee> list = new ArrayList<>();
list.add(Employee.of(21));
list.add(Employee.of(null));
list.add(Employee.of(null));
list.add(Employee.of(28));
list.add(Employee.of(23));
这个时候会报NPE:
-----------------------------
Exception in thread "main" java.lang.NullPointerException
at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
at java.util.TimSort.sort(TimSort.java:220)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1462)
可以使用Comparator.comparing
的第2个参数:
list.sort(Comparator.comparing(Employee::getAge, Comparator.nullsLast(Comparator.naturalOrder())));
list.sort(Comparator.comparing(Employee::getAge, Comparator.nullsLast(Integer::compareTo)));
list.sort(Comparator.comparing(Employee::getAge, Comparator.nullsLast(Comparable::compareTo)));
以上3中写法都可以,注意第2个参数使用了Comparator.nullsLast
让null排在最后。
与之对应的是Comparator.nullsFirst
可以null排在最前。
任意字段排序
最近项目中有个这样场景,List中是个Map<String, Object>
,需要支持Map的任意key排序。
完整代码如下:
import java.util.*;
/**
* @author cdfive
* @date 2019-05-26
*/
public class ListSortDemo2 {
public static void main(String[] args) {
List<Map<String, Object>> list = new ArrayList<>();
list.add(new HashMap<String, Object>(){{put("name", "aaa");put("age", 21);}});
list.add(new HashMap<String, Object>(){{put("name", "ccc");put("age", null);}});
list.add(new HashMap<String, Object>(){{put("name", "ddd");put("age", null);}});
list.add(new HashMap<String, Object>(){{put("name", "bbb");put("age", 28);}});
list.add(new HashMap<String, Object>(){{put("name", "aaa");put("age", 23);}});
printList(list);
printLineSep();
sort(list, "age", "asc");
printList(list);
}
public static void sort(List<Map<String, Object>> list, String sortField, String sortDirection) {
if ("desc".equals(sortDirection)) {
Comparator<Map<String, Object>> comparator = Comparator.comparing(o -> (Comparable) o.get(sortField), Comparator.nullsFirst(Comparable::compareTo));
list.sort(comparator.reversed());
} else {
Comparator<Map<String, Object>> comparator = Comparator.comparing(o -> (Comparable) o.get(sortField), Comparator.nullsLast(Comparable::compareTo));
list.sort(comparator);
}
}
public static void printList(List<?> list) {
list.stream().forEach(o -> System.out.print(o));
System.out.println();
}
public static void printLineSep() {
System.out.println("-----------------------------");
}
}
注意:
倒序使用Comparator.nullsFirst
和comparator.reversed()
,需要单独定义comparator变量,如果直接一行写:list.sort(Comparator.comparing(o -> (Comparable) o.get(sortField), Comparator.nullsFirst(Comparable::compareTo)).reversed());
会编译不通过。
正序使用Comparator.nullsLast
。