How collect prioritized values from java streams?

Viewed 73

Is it possible to collect a prioritized Stream so that I distinct on a certain object and filter max value on another object?

Example:

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.
2 Answers

One option would be this: Sort the objects by cash descending. Then use a method that wraps a Set to keep track of the already seen dates and filter the stream with it (Set::add returns true if it did not already contain the specified element).

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());
}

Result:

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

Try this.

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);

output:

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