Home > Enterprise >  Java to Kotlin Convert Fail Using Comparator & Pair
Java to Kotlin Convert Fail Using Comparator & Pair

Time:09-14

I am trying to convert this code from java to Kotlin:

            Comparator.<Pair<String, Integer>, Integer>comparing(Pair::getSecond)
                    .reversed()
                    .thenComparing(Pair::getFirst);

Intellij notes that Pair is deprecated. I am trying to find the idiomatic kotlin way to write this out. However, intellij produces this:

companion object {
        private val COUNT_COUNTRY_COMPARATOR = Comparator.comparing { obj: Pair<String?, Int?> -> obj.second }
            .reversed()
            .thenComparing { obj: Pair<String?, Int?> -> obj.first }
    }

This will not compile with the error:

Type mismatch.
Required:
TypeVariable(U)!
Found:
Int?

Between Comparator, deprecated Pair, and the strange conversion, I am wondering if there is a better way to write this in Kotlin.

CodePudding user response:

The Java-to-Kotlin converter is fairly smart and hugely helpful, but it's far from perfect; sometimes it generates code with syntax errors, and occasionally (which is worse) code that compiles but doesn't behave quite the same. So it's always worth reviewing its output carefully.

In this case, there are more concise and idiomatic ways, such as:

compareByDescending<Pair<String, Int>>{ it.second }
    .thenBy{ it.first }

This uses the top-level function compareByDescending(), and the extension function thenBy(), both of which take a ‘selector’ function.

(I find the lambda versions easier to read than function-reference versions, but no doubt the latter is possible too.)


Because the second param is numeric, you could use simple negation to reverse its order. It would then simplify to:

compareBy<Pair<String, Int>>({ -it.second }, { it.first })

However, that wouldn't work if any of the pairs could have Int.MIN_VALUE, because you can't negate that (or rather, it is its own negation), and so that would still come before everything else.

  • Related