[英]Unexpected type difference between equivalent Java and Kotlin Stream code
EDIT March 1 2016: Fair warning: this question was asked about Kotlin before 1.0.0. 编辑2016年3月1日:合理警告:在1.0.0之前,有人问过有关Kotlin的问题。 Things are different since Kotlin 1.0.0.
自Kotlin 1.0.0起,情况有所不同。 See @Jayson Minard's writing below for a Kotlin 1.0.0 answer.
有关Kotlin 1.0.0的答案,请参见下面的@Jayson Minard的文章。
In Java 8 code that uses Stream, I write things like 在使用Stream的Java 8代码中,我编写了类似
public static void main(String... args) {
Stream<Integer> integerStream = Stream.of(1,2,3);
List<Integer> integerList = integerStream.collect(Collectors.toList());
}
But in similar code written in Kotlin, I get unexpected results. 但是在用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())
}
Why would the return value of the Stream#collect
expression be of a different list type in the Kotlin code than in the Java code? 为什么Kotlin代码中的
Stream#collect
表达式的返回值与Java代码中的列表类型不同? (I'm guessing it is because of some Java Collections-specific magic in Kotlin) (我猜这是由于Kotlin中某些Java集合特有的魔术)
I think it is because List
in Java are mutable be default, where as in Kotlin they are immutable. 我认为这是因为默认情况下Java中的
List
是可变的,而Kotlin中它们是不可变的。 In the code you are using a Java specific utility, Collectors.toList
which returns a Java List
, which to Kotlin translates as a MutableList
, so in effect you are writing the same code, just the type names are different. 在代码中,您使用的是Java特定实用程序
Collectors.toList
,它返回一个Java List
,Kotlin将其转换为MutableList
,因此实际上您在编写相同的代码,只是类型名称不同。
You can do this in Kotlin 1.0: 您可以在Kotlin 1.0中执行以下操作:
val integerStream : Stream<Int> = Stream.of(1, 2, 3)
val list : List<Int> = integerStream.collect(Collectors.toList<Int>())
or 要么
val integerStream : Stream<Int> = Stream.of(1, 2, 3)
val list : MutableList<Int> = integerStream.collect(Collectors.toList<Int>())
or not care, and let inference decide: 或不在乎,让推断来决定:
val integerStream = Stream.of(1, 2, 3)
val list = integerStream.collect(Collectors.toList<Int>())
NOTE: I changed your toList()
call into toList<Int>()
to work around the issue mentioned in https://stackoverflow.com/a/35722167/3679676 注意:我将您的
toList()
调用更改为toList<Int>()
以解决https://stackoverflow.com/a/35722167/3679676中提到的问题
You can also create an extension function: 您还可以创建扩展功能:
fun <T: Any> Stream<T>.toList(): List<T> = this.collect(Collectors.toList<T>())
And then use it for any Stream<T>
to List<T>
conversion: 然后将其用于任何
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()
And this last example is already returning the read only interface of List
instead of MutableList
. 最后一个示例已经返回
List
的只读接口,而不是MutableList
。 For the difference between these and other mapped interfaces in Kotlin, see the docs for Java Interop, mapped types . 有关Kotlin中这些映射接口与其他映射接口之间的区别,请参阅Java Interop映射类型的文档。
Lastly, one other variant is to convert to a Sequence
and stay lazy, since it is the Kotlin equivalent of a Stream
. 最后,另一种变体是转换为
Sequence
并保持惰性,因为它与Stream
的Kotlin等效。
fun <T: Any> Stream<T>.asSequence(): Sequence<T> = this.iterator().asSequence()
Or Stream.iterator()
is similar, but not the same. 或
Stream.iterator()
相似,但不相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.