实体类
/**
* [Employee(name=John, age=25, salary=3000.0, mobile=9922001),
* Employee(name=Ace, age=22, salary=2000.0, mobile=5924001),
* Employee(name=Keith, age=35, salary=4000.0, mobile=3924401)]
*/
@Data
class Employee {
private String name;
private int age;
private double salary;
private long mobile;
// constructors, getters & setters
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Employee{");
sb.append("name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append(", salary=").append(salary);
sb.append(", mobile=").append(mobile);
sb.append('}');
return sb.toString();
}
}
使用外部比较器Comparator进行排序
当我们需要对集合的元素进行排序的时候,可以使用java.util.Comparator 创建一个比较器来进行排序。Comparator接口同样也是一个函数式接口,我们可以把使用lambda表达式。如下示例,
package com.common;
import java.util.*;
import java.util.stream.Collectors;
public class ComparatorTest {
public static void main(String[] args) {
Employee e1 = new Employee("John", 25, 3000, 9922001);
Employee e2 = new Employee("Ace", 22, 2000, 5924001);
Employee e3 = new Employee("Keith", 35, 4000, 3924401);
List<Employee> employees = new ArrayList<>();
employees.add(e1);
employees.add(e2);
employees.add(e3);
/**
* sort 对象接收一个 Comparator 函数式接口,可以传入一个lambda表达式
*/
employees.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));
Collections.sort(employees, (o1, o2) -> o1.getName().compareTo(o2.getName()));
employees.forEach(System.out::println);
}
}
使用 Comparator.comparing 进行排序
comparing 方法一
查看 Comparator 类内部实现,还有一个 comparing 方法,实现如下,
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
其返回值是 (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); 一个lambda表达式,也就是一个Compator 。所以上面那个例子也可以改造成 如下,
/**
* Comparator.comparing 方法的使用
*
* comparing 方法接收一个 Function 函数式接口 ,通过一个 lambda 表达式传入
*
*/
employees.sort(Comparator.comparing(e -> e.getName()));
/**
* 该方法引用 Employee::getName 可以代替 lambda表达式
*/
employees.sort(Comparator.comparing(Employee::getName));
comparing 方法二
public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}
和comparing 方法一不同的是 该方法多了一个参数 keyComparator ,keyComparator 是创建一个自定义的比较器。
Collections.sort(employees, Comparator.comparing(
Employee::getName, (s1, s2) -> {
return s2.compareTo(s1);
}));
使用 Comparator.reversed 进行排序
返回相反的排序规则,
/**
* 相反的排序规则
*/
Collections.sort(employees, Comparator.comparing(Employee::getName).reversed());
employees.forEach(System.out::println);
输出,
Employee{name='Keith', age=35, salary=4000.0, mobile=3924401}
Employee{name='John', age=25, salary=3000.0, mobile=9922001}
Employee{name='Ace', age=22, salary=2000.0, mobile=5924001}
使用 Comparator.nullsFirst进行排序
当集合中存在null元素时,可以使用针对null友好的比较器,null元素排在集合的最前面
employees.add(null); //插入一个null元素
Collections.sort(employees, Comparator.nullsFirst(Comparator.comparing(Employee::getName)));
employees.forEach(System.out::println);
Collections.sort(employees, Comparator.nullsLast(Comparator.comparing(Employee::getName)));
employees.forEach(System.out::println);
使用 Comparator.thenComparing 排序
首先使用 name 排序,紧接着在使用ege 排序,来看下使用效果
Collections.sort(employees, Comparator.comparing(Employee::getAge).thenComparing(Employee::getName));
employees.forEach(System.out::println);
reversed()和Comparator.reverseOrder()排序区别
-
Comparator.comparing(类::属性一).reversed();
-
Comparator.comparing(类::属性一,Comparator.reverseOrder());
方式 1:是得到排序结果后再排序;
方式2:是直接进行排序,很多人会混淆导致理解出错, 该方式更好理解
List<Object> list;
//对象集合以类属性一升序排序
list.stream().sorted(Comparator.comparing(类::属性一));
//对象集合以类属性一降序排序,两种方式写法对比:
list.stream().sorted(Comparator.comparing(类::属性一).reversed());//方式1:先以属性一升序,结果再进行降序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()));//方式2:直接以属性一降序
//对象集合以类属性一升序、属性二升序排序
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二));
//对象集合以类属性一降序、属性二升序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二));//方式1:先以属性一升序,升序结果进行属性一降序,再进行属性二升序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二));//方式2:先以属性一降序,再进行属性二升序
//返回 对象集合以类属性一降序 属性二降序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,升序结果进行属性一降序,再进行属性二降序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一降序,再进行属性二降序
//返回 对象集合以类属性一升序 属性二降序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二).reversed());//先以属性一升序,升序结果进行属性一降序,再进行属性二升序,结果进行属性一降序属性二降序
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,再进行属性二降序
//空/Null数据排序
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(item -> item.属性二, Comparator.nullsLast(Date::compareTo))).collect(Collectors.toList());
//空/Null数据分组
Map<String, List<类>> map = list.stream().collect(Collectors.groupingBy(item -> {
if (item.属性一 == null || item.属性一.equals("")) {
return "";
}
return DateFormat.getDateInstance().format(item.属性一);
}))