等效的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中提到的问&#x9898;

你也可以创建一个扩展函数:

 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 ,所以实际上你正在编写相同的代码,只是类型名称是不同的。