在 Java 8 中使用流畅的链接对集合进行排序
Sorting a collection using fluent chaining in Java 8
给定一个 class.
public class Entity {
private Long id;
private String prodName;
private BigDecimal price;
// Constructors + getters + setters + hashcode() + equals() + toString().
}
正在构建 Entity
的列表。
List<Entity> list = new ArrayList<>();
Entity entity = new Entity();
entity.setId(1L);
entity.setProdName("A");
entity.setPrice(new BigDecimal(10));
list.add(entity);
entity = new Entity();
entity.setId(2L);
entity.setProdName("B");
entity.setPrice(new BigDecimal(20));
list.add(entity);
entity = new Entity();
entity.setId(3L);
entity.setProdName("C");
entity.setPrice(new BigDecimal(30));
list.add(entity);
entity = new Entity();
entity.setId(4L);
entity.setProdName("D");
entity.setPrice(new BigDecimal(40));
list.add(entity);
entity = new Entity();
entity.setId(5L);
entity.setProdName("E");
entity.setPrice(new BigDecimal(50));
list.add(entity);
entity = new Entity();
entity.setId(6L);
entity.setProdName("F");
entity.setPrice(new BigDecimal(60));
list.add(entity);
entity = new Entity();
entity.setId(7L);
entity.setProdName("F");
entity.setPrice(new BigDecimal(60));
list.add(entity);
正在尝试按 price
和 prodName
降序排列列表,然后按 id
升序排列列表。
Comparator<Entity> comparator = Comparator.comparing(Entity::getPrice).reversed();
comparator = comparator.thenComparing(Entity::getProdName).reversed();
comparator = comparator.thenComparingLong(Entity::getId);
list = list.stream().sorted(comparator).collect(Collectors.toList());
// Or Collections.sort(list, comparator);
list.stream().forEachOrdered(l -> System.out.println(l.getId() + " : " + l.getPrice() + " : " + l.getProdName()));
执行排序后,列表应如下所示。
6 : 60 : F
7 : 60 : F
5 : 50 : E
4 : 40 : D
3 : 30 : C
2 : 20 : B
1 : 10 : A
但是排序后的列表如下所示。
1 : 10 : A
2 : 20 : B
3 : 30 : C
4 : 40 : D
5 : 50 : E
6 : 60 : F
7 : 60 : F
排序的列表不符合给定的标准(按 price
和 prodName
降序,按 id
升序)。
还需要做什么?
考虑您的代码评论:
Comparator<Entity> comparator = Comparator.comparing(Entity::getPrice).reversed(); // compare by descending price
comparator = comparator.thenComparing(Entity::getProdName) // then compare by ascending name
.reversed(); // then reverse this order: so you now sort by ascending price and descending name
comparator = comparator.thenComparingLong(Entity::getId); // and finally compare by ascending id
所以最后的比较器是:升序价格,降序名称然后升序 ID,这正是您所得到的结果。
因此,错误是您错误地将调用链接到 reversed()
。
以下将起作用:
Comparator<Entity> comparator = Comparator.comparing(Entity::getPrice).reversed(); //sort by descending price
comparator = comparator.thenComparing(Comparator.comparing(Entity::getProdName).reversed()); // then sort by descending name
comparator = comparator.thenComparingLong(Entity::getId); // then sort by ascending id
每次调用 reversed() 时都会反转整个比较器。相反,只需按照您的描述进行操作即可:
Comparator<Entity> comparator = Comparator.comparing(Entity::getPrice,
Comparator.reverseOrder());
comparator = comparator.thenComparing(Entity::getProdName,
Comparator.reverseOrder());
comparator = comparator.thenComparingLong(Entity::getId);
list = list.stream().sorted(comparator).collect(Collectors.toList());
list.stream().forEachOrdered(l -> System.out.println(l.getId() + " : " + l.getPrice() + " : " + l.getProdName()));
给定一个 class.
public class Entity {
private Long id;
private String prodName;
private BigDecimal price;
// Constructors + getters + setters + hashcode() + equals() + toString().
}
正在构建 Entity
的列表。
List<Entity> list = new ArrayList<>();
Entity entity = new Entity();
entity.setId(1L);
entity.setProdName("A");
entity.setPrice(new BigDecimal(10));
list.add(entity);
entity = new Entity();
entity.setId(2L);
entity.setProdName("B");
entity.setPrice(new BigDecimal(20));
list.add(entity);
entity = new Entity();
entity.setId(3L);
entity.setProdName("C");
entity.setPrice(new BigDecimal(30));
list.add(entity);
entity = new Entity();
entity.setId(4L);
entity.setProdName("D");
entity.setPrice(new BigDecimal(40));
list.add(entity);
entity = new Entity();
entity.setId(5L);
entity.setProdName("E");
entity.setPrice(new BigDecimal(50));
list.add(entity);
entity = new Entity();
entity.setId(6L);
entity.setProdName("F");
entity.setPrice(new BigDecimal(60));
list.add(entity);
entity = new Entity();
entity.setId(7L);
entity.setProdName("F");
entity.setPrice(new BigDecimal(60));
list.add(entity);
正在尝试按 price
和 prodName
降序排列列表,然后按 id
升序排列列表。
Comparator<Entity> comparator = Comparator.comparing(Entity::getPrice).reversed();
comparator = comparator.thenComparing(Entity::getProdName).reversed();
comparator = comparator.thenComparingLong(Entity::getId);
list = list.stream().sorted(comparator).collect(Collectors.toList());
// Or Collections.sort(list, comparator);
list.stream().forEachOrdered(l -> System.out.println(l.getId() + " : " + l.getPrice() + " : " + l.getProdName()));
执行排序后,列表应如下所示。
6 : 60 : F
7 : 60 : F
5 : 50 : E
4 : 40 : D
3 : 30 : C
2 : 20 : B
1 : 10 : A
但是排序后的列表如下所示。
1 : 10 : A
2 : 20 : B
3 : 30 : C
4 : 40 : D
5 : 50 : E
6 : 60 : F
7 : 60 : F
排序的列表不符合给定的标准(按 price
和 prodName
降序,按 id
升序)。
还需要做什么?
考虑您的代码评论:
Comparator<Entity> comparator = Comparator.comparing(Entity::getPrice).reversed(); // compare by descending price
comparator = comparator.thenComparing(Entity::getProdName) // then compare by ascending name
.reversed(); // then reverse this order: so you now sort by ascending price and descending name
comparator = comparator.thenComparingLong(Entity::getId); // and finally compare by ascending id
所以最后的比较器是:升序价格,降序名称然后升序 ID,这正是您所得到的结果。
因此,错误是您错误地将调用链接到 reversed()
。
以下将起作用:
Comparator<Entity> comparator = Comparator.comparing(Entity::getPrice).reversed(); //sort by descending price
comparator = comparator.thenComparing(Comparator.comparing(Entity::getProdName).reversed()); // then sort by descending name
comparator = comparator.thenComparingLong(Entity::getId); // then sort by ascending id
每次调用 reversed() 时都会反转整个比较器。相反,只需按照您的描述进行操作即可:
Comparator<Entity> comparator = Comparator.comparing(Entity::getPrice,
Comparator.reverseOrder());
comparator = comparator.thenComparing(Entity::getProdName,
Comparator.reverseOrder());
comparator = comparator.thenComparingLong(Entity::getId);
list = list.stream().sorted(comparator).collect(Collectors.toList());
list.stream().forEachOrdered(l -> System.out.println(l.getId() + " : " + l.getPrice() + " : " + l.getProdName()));