Nuñito Calzada
Nuñito Calzada

Reputation: 2136

sorted in stream is not applicable

I have this piece of Java8 code:

Set<Purchase> purchases = 
    user.getAcquisitions()
        .parallelStream()
        .map(a -> a.getPurchases())
    .sorted(Comparator.comparing(Purchase::getPurchaseDate).reversed());

But I have this compilation error and I don't know why:

The method sorted(Comparator<? super Set<Purchase>>) in the type Stream<Set<Purchase>> is not applicable for the arguments 
 (Comparator<Purchase>)

Upvotes: 4

Views: 934

Answers (4)

ctenescu
ctenescu

Reputation: 104

The a.getPurchases() gives you a set, and your comparator is comparing elements of the set, not sets.

Based on your expected output, I understand you want to get the set which has the latest purchase date. If each set contains only same purchase date purchases, you can create your comparator like this:

 .sorted(Comparator.comparing(purchases -> purchases.iterator().next(), (p1, p2) -> -p1.compareTo(p2)));

If purchase dates differ inside a set, you need to get max (or min) purchase date inside a set, then compare that in between the sets, something like:

final Stream<Set<Purchase>> sorted = acquisitions.stream()
    .map(Acquisition::getPurchases)
    .sorted(Comparator.comparing(purchases ->
            Collections.max(purchases, Comparator.comparing(Purchase::getPurchaseDate)).getPurchaseDate(),
            (date1, date2) -> -date1.compareTo(date2)));

Upvotes: 1

Joe C
Joe C

Reputation: 15704

After .map(a -> a.getPurchases()), you appear to be expecting a Stream<Purchase>, but what you really have is a Stream<Set<Purchase>>.

If a Stream<Purchase> is indeed what you want, instead you should use

.flatMap(a -> a.getPurchases().stream())

Upvotes: 9

Ousmane D.
Ousmane D.

Reputation: 56453

To expand upon Joe's answer, it seems like you want a Set<Purchase> in sorted order (for whatever reason that may be), given you have a good reason to do so in which case you can use a LinkedHashSet:

user.getAcquisitions()
    .parallelStream()
    .flatMap(e -> e.getPurchase().stream())
    .sorted(Comparator.comparing(Purchase::getPurchaseDate).reversed())
    .collect(toCollection(LinkedHashSet::new));
  • flatMap flattens the nested Set<Purchase> into a Stream<Purchase>
  • it then sorts the elements according to the provided comparator
  • then collects the elements into a LinkedHashSet implementation which respects insertion order.

btw note that you could as well just do:

user.getAcquisitions()
    .parallelStream()
    .flatMap(e -> e.getPurchase().stream())
    .distinct()
    .sorted(Comparator.comparing(Purchase::getPurchaseDate).reversed())
    .collect(toCollection(ArrayList::new));

so, depending on the context you're using the resulting elements you might be better off collecting to a list implementation.

  • flatMap flattens the nested Set<Purchase> into a Stream<Purchase>
  • distinct returns a new stream of the unique objects according to the equals method.
  • it then sorts the elements according to the provided comparator
  • finally, it then collects the element from the stream into an ArrayList implementation.

Upvotes: 2

ETO
ETO

Reputation: 7279

Try doing it this way:

 Set<Purchase> purchases = 
    user.getAcquisitions()
        .parallelStream()
        .map(Acquisition::getPurchases)
        .flatMap(Set::stream)
        .collect(Collectors.toCollection(TreeSet::new));

Upvotes: 0

Related Questions