如何从 java 流中收集优先值?

How collect prioritized values from java streams?

是否可以收集优先流,以便我区分某个对象并过滤另一个对象的最大值?

示例:

class Foo {
   private LocalDate date;
   private Integer cash;
}

List<Foo> myNewFoo = foos.stream().distinct(SOMETHING).collect(toList()) 
// distinct date, if more than one date of same value then choose max value of cash.

试试这个。

List<Foo> foos = List.of(
    new Foo(LocalDate.of(2021, 1, 1), 100),
    new Foo(LocalDate.of(2021, 1, 1), 200),
    new Foo(LocalDate.of(2021, 1, 2), 300),
    new Foo(LocalDate.of(2021, 1, 2), 400),
    new Foo(LocalDate.of(2021, 1, 3), 500));
List<Foo> myNewFoo = new ArrayList<>(foos.stream()
    .collect(Collectors.toMap(Foo::getDate, Function.identity(),
        (a, b) -> a.getCash() > b.getCash() ? a : b, TreeMap::new))
    .values());
System.out.println(myNewFoo);

输出:

[Foo(2021-01-01,200), Foo(2021-01-02,400), Foo(2021-01-03,500)]

一个选项是:按 cash 降序排列对象。然后使用包装 Set 的方法来跟踪已经看到的日期并用它过滤流(Set::add returns 如果它还没有包含指定的元素则为真)。

public static void main(String[] args) {
    List<Foo> foos = new ArrayList<>();
    foos.add(new Foo(LocalDate.of(2021, 6, 1), 600));
    foos.add(new Foo(LocalDate.of(2021, 6, 3), 200));
    foos.add(new Foo(LocalDate.of(2021, 6, 4), 300));
    foos.add(new Foo(LocalDate.of(2021, 6, 2), 400));
    foos.add(new Foo(LocalDate.of(2021, 6, 3), 800));
    foos.add(new Foo(LocalDate.of(2021, 6, 1), 300));

    List<Foo> myNewFoo = foos.stream()
            .sorted(Comparator.comparing(Foo::getCash).reversed())
            .filter(distinctByDate())
            .collect(Collectors.toList());

    System.out.println(myNewFoo);
}

public static Predicate<Foo> distinctByDate() {
    Set<LocalDate> seen = new HashSet<>();
    return foo -> seen.add(foo.getDate());
}

结果:

[(2021-06-03,800), (2021-06-01,600), (2021-06-02,400), (2021-06-04,300)]