使用Java 8中的流畅链接对集合进行排序

Tin*_*iny 4 java sorting comparator java-8 java-stream

给一个班级.

public class Entity {

    private Long id;
    private String prodName;
    private BigDecimal price;

    // Constructors + getters + setters + hashcode() + equals() + toString().
}
Run Code Online (Sandbox Code Playgroud)

构建一个列表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);
Run Code Online (Sandbox Code Playgroud)

试图以按由降序排列的列表priceprodName,然后通过升序排列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()));
Run Code Online (Sandbox Code Playgroud)

执行排序后,列表应如下所示.

6 : 60 : F
7 : 60 : F
5 : 50 : E
4 : 40 : D
3 : 30 : C
2 : 20 : B
1 : 10 : A
Run Code Online (Sandbox Code Playgroud)

但是,在执行排序之后,列表如下所示.

1 : 10 : A
2 : 20 : B
3 : 30 : C
4 : 40 : D
5 : 50 : E
6 : 60 : F
7 : 60 : F
Run Code Online (Sandbox Code Playgroud)

已排序的列表不是根据给定的准则(通过递减顺序priceprodName与由升序id).

还有什么需要做的?

JB *_*zet 7

每次调用reverse()时,你都会反转整个比较器.相反,只需按照您的描述说:

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()));
Run Code Online (Sandbox Code Playgroud)

  • 当然,认识到`reversed()`适用于整个比较器的程序员可能只使用`Comparator.comparing(Entity :: getPrice).thenComparing(Entity :: getProdName).reversed().thenComparingLong(Entity :: getId) `实现同样的目标...... (4认同)

Tun*_*aki 5

考虑您的代码注释:

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
Run Code Online (Sandbox Code Playgroud)

因此,最终的比较器是:价格升序,名称降序,然后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
Run Code Online (Sandbox Code Playgroud)