等效的Java和Kotlin Stream代码之间意外的类型差异
编辑2016年3月1日:公平的警告:这个问题被问到1.0.0之前的Kotlin。 从Kotlin 1.0.0开始,情况就不一样了。 请参阅下面的@Jayson Minard的Kotlin 1.0.0答案。
在使用Stream的Java 8代码中,我写了类似的东西
public static void main(String... args) { Stream<Integer> integerStream = Stream.of(1,2,3); List<Integer> integerList = integerStream.collect(Collectors.toList()); }
但是在Kotlin编写的类似代码中,我得到了意想不到的结果。
public fun main(args: Array<String>) { val integerStream : Stream<Int> = Stream.of(1, 2, 3) // this is what I expect to write, like the Java 8 code, but is a compilation error: // "required: java.util.List<in kotlin.Int> found: kotlin.MutableList<in kotlin.Int!" // val list : java.util.List<in Int> = integerStream.collect(Collectors.toList()) // I must instead write this val list : MutableList<in Int> = integerStream.collect(Collectors.toList()) }
为什么Stream#collect
表达式的返回值在Kotlin代码中与Java代码中的列表类型不同? (我猜这是因为Kotlin的一些Java Collections特有的魔法)
你可以在Kotlin 1.0中做到这一点:
val integerStream : Stream<Int> = Stream.of(1, 2, 3) val list : List<Int> = integerStream.collect(Collectors.toList<Int>())
要么
val integerStream : Stream<Int> = Stream.of(1, 2, 3) val list : MutableList<Int> = integerStream.collect(Collectors.toList<Int>())
或者不在意,并且让我们推断:
val integerStream = Stream.of(1, 2, 3) val list = integerStream.collect(Collectors.toList<Int>())
注意:我将您的toList()
调用更改为toList<Int>()
以解决https://stackoverflow.com/a/35722167/3679676中提到的问题
你也可以创建一个扩展函数:
fun <T: Any> Stream<T>.toList(): List<T> = this.collect(Collectors.toList<T>())
然后用它来进行Stream<T>
到List<T>
转换:
val integerStream = Stream.of(1, 2, 3) val list = integerStream.toList() val stringStream = Stream.of("a", "b", "c") val stringList = stringStream.toList()
最后这个例子已经返回List
的只读接口而不是MutableList
。 有关这些与Kotlin中其他映射接口的区别,请参阅Java Interop文档,映射类型 。
最后,另一个变体是转换为Sequence
并保持懒惰,因为它是Stream
的Kotlin等价物。
fun <T: Any> Stream<T>.asSequence(): Sequence<T> = this.iterator().asSequence()
或Stream.iterator()
是类似的,但不一样。
我认为这是因为Java中的List
是可变的,默认情况下,在Kotlin中它们是不可变的。 在代码中,你正在使用一个Java特定的实用程序Collectors.toList
,它返回一个Java List
,这个Java List
被Kotlin翻译成一个MutableList
,所以实际上你正在编写相同的代码,只是类型名称是不同的。