0

[ Note: I'm fully aware of the answers provided in this SO question ]

I have a set of records that need to be matched/ranked in the context of an other object.

The comparisons needed to determine the ranking score are "expensive" so simply making these classes implement Comparable (as indicated in the other SO question) would make it way too slow.

So I came up with essentially (severely simplified code!) this:

input
    .stream()
    // Do the calculation and cache the result in a Pair
    .map(record -> Pair.of(record, record.doCalculation(context)))
    .filter(record -> record.getRight() > 0)
 
    // Sort by the calculated value
    .sorted(Comparator.comparingLong(Pair::getRight))

    // and do something with it.
    .forEachOrdered(record -> 
        log.info("Record: {} --> {}", record.getRight(), record.getLeft())
    );

This sorts the records into an increasing score ordering:

.sorted(Comparator.comparingLong(Pair::getRight))

The problem I need to solve is that I need a decreasing score ordering (i.e. reversed).

Initially expected this to work

.sorted(Comparator.comparingLong(Pair::getRight).reversed())

I checked the .reversed() method and it seems to return a comparator (class Collections.ReverseComparator2) that simply swaps the two provided values before feeding it into the original comparator.

This however fails (commandline) with a

 incompatible types: cannot infer type-variable(s) T
    (argument mismatch; invalid method reference
      method getRight in class org.apache.commons.lang3.tuple.Pair<L,R> cannot be applied to given types
        required: no arguments
        found: java.lang.Object
        reason: actual and formal argument lists differ in length)

In IntelliJ it gives a different error: Non-static method cannot be referenced from a static context

I suspect it has something to do how streams and generics work together.

My question is that I do not yet understand why this fails.

What am I doing wrong here?


NOTE: For now I'm using this ugly workaround:

.sorted(Comparator.comparingLong(p -> p.getRight()*-1L))

Update: Solved with the suggestions from Gaël J

.sorted((Comparator.comparingLong(Pair<MyThing, Long>::getRight)).reversed())

Niels Basjes
  • 10,424
  • 9
  • 50
  • 66
  • 2
    Did you try expliciting types? There are some corner cases with type inference in lambdas – Gaël J Sep 05 '21 at 12:20
  • @GaëlJ What would that look like? I have tried several ways to put in an explicit cast and failed. – Niels Basjes Sep 05 '21 at 12:26
  • I found this to work: `.sorted((Comparator.comparingLong(p -> ((Pair)p).getRight())).reversed()` with warnings about unchecked casting. – Niels Basjes Sep 05 '21 at 12:33
  • 1
    Solved: `.sorted((Comparator.comparingLong(Pair::getRight)).reversed())` – Niels Basjes Sep 05 '21 at 12:35
  • 1
    `.sorted((Comparator.>comparingLong(Pair::getRight)).reversed())` should also work. Or alternatively this: `Comparator> comp = Comparator.comparingLong(Pair::getRight).reversed();` then use it as `.sorted(comp)` – Lino Sep 05 '21 at 12:45

0 Answers0