I need to sort List<String> by the number of occurrences in my list (DESC), and to remove repetitions from there. I wrote this working algorithm in java:
private List<String> sortByFrequency(List<String> sequence) {
return
sequence.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue(Comparator.reverseOrder())
.thenComparing(Map.Entry.comparingByKey()))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
but it doesn't work for Kotlin: kotlin code
because I get the following exception:
Type inference failed. Expected type mismatch:
required:
Collector<in String!, Any!, Long!>!
found:
Collector<String!, *, Long!>!
and can't figure out how to resolve it. maybe can you tell me?
Let Kotlin figure out the types for you. Don't specify the type parameters unless you need to. Kotlin will try its best to find the correct types.
There is only one place that you need to specify the type parameters, and that is the Map.Entry.comparingByValue call.
This compiles:
fun sortByFrequency(sequence: List<String>): List<String?>? {
return sequence.stream()
.collect(Collectors.groupingBy({ it }, Collectors.counting()))
.entries.stream()
.sorted(
Map.Entry.comparingByValue<String, Long>(Comparator.reverseOrder())
.thenComparing(Map.Entry.comparingByKey())
)
.map { it.key }
.collect(Collectors.toList())
}
However, the code still feels very Java-ish. IMO, this is more idiomatic Kotlin:
fun sortByFrequency(sequence: List<String>): List<String> {
val comparator = compareByDescending<Map.Entry<String, Int>> { it.value }
.thenBy { it.key }
return sequence.groupingBy { it }.eachCount().entries
.sortedWith(comparator).map { it.key }
}
Notice the use of groupingBy and eachCount.
The problem comes that * and Any are not meaning the same thing. They are treated as distinct types, so the compilation fails. In fact * can mean in Nothing or out Any? in Kotlin, depending on the context.
More info on the topic: https://kotlinlang.org/docs/generics.html#star-projections
In your case Kotlin should be able to infer the correct types for the collector for you, so can leave them out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With