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