等效Java和Kotlin Stream代码之间的意外类型差异

时间:2015-11-15 01:05:33

标签: java generics kotlin

编辑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的魔法)

2 个答案:

答案 0 :(得分:3)

我认为这是因为Java中的List是可变的是默认的,而在Kotlin中它们是不可变的。 在代码中,您使用的是Java特定的实用程序Collectors.toList,它返回一个Java List,它将Kotlin转换为MutableList,因此实际上您正在编写相同的代码,只是类型名称不同。

答案 1 :(得分:1)

您可以在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, mapped types的文档。

最后,另一个变体是转换为Sequence并保持懒惰,因为它是Kotlin等效的Stream

fun <T: Any> Stream<T>.asSequence(): Sequence<T> = this.iterator().asSequence()

Stream.iterator()相似,但不一样。