将 Java 频率排序转换为 Kotlin
Convert Java Frequency Sort to Kotlin
我需要按列表中出现的次数 (DESC) 对 List<String>
进行排序,并从那里删除重复项。我在 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());
}
但它不适用于 Kotlin:
kotlin code
因为我得到以下异常:
Type inference failed. Expected type mismatch:
required:
Collector<in String!, Any!, Long!>!
found:
Collector<String!, *, Long!>!
并且不知道如何解决它。也许你能告诉我吗?
问题来了,*
和Any
不是一个意思。它们被视为不同的类型,因此编译失败。事实上,*
在 Kotlin 中可能表示 in Nothing
或 out Any?
,具体取决于上下文。
有关该主题的更多信息:
https://kotlinlang.org/docs/generics.html#star-projections
在您的情况下,Kotlin 应该能够为您推断出收集器的正确类型,因此可以将它们排除在外。
让 Kotlin 为您找出类型。除非需要,否则不要指定类型参数。 Kotlin 会尽力找到正确的类型。
只有一个地方需要指定类型参数,那就是Map.Entry.comparingByValue
调用。
这样编译:
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())
}
但是,代码仍然感觉很 Java-ish。 IMO,这是更惯用的 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 }
}
注意 groupingBy
and eachCount
.
的使用
我需要按列表中出现的次数 (DESC) 对 List<String>
进行排序,并从那里删除重复项。我在 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());
}
但它不适用于 Kotlin: kotlin code
因为我得到以下异常:
Type inference failed. Expected type mismatch:
required:
Collector<in String!, Any!, Long!>!
found:
Collector<String!, *, Long!>!
并且不知道如何解决它。也许你能告诉我吗?
问题来了,*
和Any
不是一个意思。它们被视为不同的类型,因此编译失败。事实上,*
在 Kotlin 中可能表示 in Nothing
或 out Any?
,具体取决于上下文。
有关该主题的更多信息: https://kotlinlang.org/docs/generics.html#star-projections
在您的情况下,Kotlin 应该能够为您推断出收集器的正确类型,因此可以将它们排除在外。
让 Kotlin 为您找出类型。除非需要,否则不要指定类型参数。 Kotlin 会尽力找到正确的类型。
只有一个地方需要指定类型参数,那就是Map.Entry.comparingByValue
调用。
这样编译:
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())
}
但是,代码仍然感觉很 Java-ish。 IMO,这是更惯用的 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 }
}
注意 groupingBy
and eachCount
.