Comparator代表一个比较器,比较的是两个对象。
/**
* @param o1 要比较的第一个对象;
* @param o2 要比价的第二个对象;
* @reture 若o1小于02,返回负整数;o1等于o2返回0;o1大于o2返回正整数;
**/
int compare(T o1,T o2)
Comparator [肯派瑞特]
比较器
comparable[抗母普瑞堡]
可比较的
1. comparable和comparator的区别
comparable和comparator都是用于比较数据大小,字母意思前者是形容词,而后者是名词。即实现comparable接口的类,具有了比较大小的功能。而实现comparator接口的类,是一个比较器。
在Collections工具类中,有一个排序方法sort,此方法可以传入一个集合,也可以传入一个集合和比较器。前者集合中的元素必须要实现comparable接口,而后者按照我们传入的comparator接口进行排序。
2. 返回值和排升/降序的联系
comparable
接口方法是compareTo(T o)
this对象和o对象的比较;
comparator
接口方法是compare(T o1,T o2)
o1对象和o2对象的比较;
方法的返回值代表的是o1(this)的顺序,而并非o1和o2的大小关系。只要返回负数,那么o1便在o2前方。返回正整数,o1在o2后方。
默认为升序排列。
在API中,明确表示出this(o1)减去o2。
故默认请求下,o1<o2时,才会返回负数。
如何设置使其降序排序?
若-(o1减去o2),便是降序排列。
我们可以将结果取反,那么排序,也是相反的,即为升序排序。
3. Lambda实现多条件排序
public class ListOrder {
private static List<User> userList = new ArrayList<>();
private static String DATA_FORMAT = "yyyy-MM-dd HH:mm";
//已完成
private static Integer END = 3;
//进行中
private static Integer ONDOING = 2;
//构建数据
static {
Date date = new Date();
Date d1 = DateUtils.addHours(date, -1);
String s1 = DateFormatUtils.format(d1, DATA_FORMAT);
User u1 = new User(2, s1);
Date d2 = DateUtils.addHours(date, -3);
String s2 = DateFormatUtils.format(d2, DATA_FORMAT);
User u2 = new User(2, s2);
Date d3 = DateUtils.addHours(date, -2);
String s3 = DateFormatUtils.format(d3, DATA_FORMAT);
User u3 = new User(3, s3);
Date d4 = DateUtils.addHours(date, -2);
String s4 = DateFormatUtils.format(d4, DATA_FORMAT);
User u4 = new User(2, s4);
Date d5 = DateUtils.addDays(date, -1);
String s5 = DateFormatUtils.format(d5, DATA_FORMAT);
User u5 = new User(3, s5);
//进行中的要排在已完成的后面,两个模块再按时间排序
userList.add(u1);
userList.add(u2);
userList.add(u3);
userList.add(u4);
userList.add(u5);
}
public static void main(String[] args) {
//type字段升序排序,time字段升序排序。
List<User> users2 = userList.stream().sorted(
Comparator.comparing(User::getType).thenComparing(User::getTime))
.collect(Collectors.toList());
System.out.println(users2);
//type字段升序排序,time字段降序排列。
List<User> users = userList.stream().sorted(
Comparator.comparing(User::getType).reversed()
.thenComparing(User::getTime).reversed())
.collect(Collectors.toList());
System.out.println(users);
//Time字段降序排序,type字段降序排序。
List<User> users3 = userList.stream().sorted(
Comparator.comparing(User::getType).
thenComparing(User::getTime).reversed())
.collect(Collectors.toList());
System.out.println(users3);
//type字段升序排序,time字段降序排序。
List<User> users4 = userList.stream().
sorted(Comparator.comparing(User::getType).reversed().
thenComparing(User::getTime)).
collect(Collectors.toList());
System.out.println(users4);
/**
* 第二种方式:o1(this)-o2便是升序排序,否则便是降序排序。
*/
//按照type进行升序排序,按照time进行降序排序
List<User> users5 = userList.stream().
sorted(Comparator.comparing(User::getType).
thenComparing((o1, o2) -> o2.time.compareTo(o1.time)))
.collect(Collectors.toList());
System.out.println(users5);
/**
* 不借助stream也可以进行排序
*/
userList.sort(Comparator.comparing(User::getType).reversed());
}
/**
* 用户信息
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class User {
private Integer type;
private String time;
}
}
若属性值为null,那么使用sorted进行排序时会出现空指针异常。解决方案:
//getTime使用降序排列,若是time字段为null,那么排在首位
userList.sort(Comparator.comparing(User::getTime,
Comparator.nullsFirst(Comparator.reverseOrder())));
System.out.println(userList);