Kotlin和Immutable Collections?

tmn*_*tmn 37 kotlin

我正在学习Kotlin,看起来我可能希望在明年使用它作为我的主要语言.然而,我不断得到相互矛盾的研究,Kotlin有或没有不可变的集合,我想弄清楚我是否需​​要使用Google Guava.

有人可以给我一些指导吗?它默认使用不可变集合吗?什么操作符返回可变或不可变的集合?如果没有,是否有计划实施它们?

nha*_*man 30

List来自标准库的Kotlin 是只读的:

interface List<out E> : Collection<E> (source)
Run Code Online (Sandbox Code Playgroud)

通用的有序元素集合.此接口中的方法仅支持对列表的只读访问; 通过MutableList接口支持读/写访问.

参数
E - 列表中包含的元素类型.

如上所述,还有 MutableList

interface MutableList<E> : List<E>, MutableCollection<E> (source)
Run Code Online (Sandbox Code Playgroud)

支持添加和删除元素的通用有序元素集合.

参数
E - 列表中包含的元素类型.

因此,Kotlin通过其接口强制执行只读行为,而不是像默认Java实现那样在运行时抛出异常.

同样,有MutableCollection,MutableIterable,MutableIterator,MutableListIterator,MutableMap,和MutableSet,看到STDLIB文档.

  • Kotlin收藏品只读,而不是一成不变的@nhaarman.我建议编辑你的答案. (2认同)

vod*_*dan 19

这是令人困惑的,但有三种,而不是两种类型的不变性:

  1. 可变 - 你应该改变收藏(Kotlin's MutableList)
  2. Readonly - 你不应该改变它(Kotlin's List)但是有些东西可能(强制转换为Mutable,或者从Java改变)
  3. 永恒 - 没有人可以改变它(番石榴的不可变集合)

因此,在情况(2)List只是一个没有变异方法的接口,但是如果你将它转换为实例,你可以更改它MutableList.

使用Guava(案例(3)),即使使用演员或其他线程,您也可以安全地更改集合.

为了直接使用Java集合,Kotlin选择了readonly,因此使用Java集合没有任何开销或转换.

  • Kotlin`List`是只读的,不是一成不变的.其他调用者(例如Java)可能会更改列表.Kotlin调用者可能会列出并更改它.没有不可改变的保护. (3认同)

Jay*_*ard 14

正如您在其他答案中看到的那样,Kotlin具有可读集合的只读接口,可让您通过只读镜头查看集合.但是可以通过转换或从Java操纵来绕过该集合.但是在合作的Kotlin代码中很好,大多数用法都不需要真正的不可变集合,如果你的团队避免使用集合的可变形式,那么你可能不需要完全不可变的集合.

Kotlin集合允许复制变更突变以及惰性突变.因此,要回答你的问题的一部分,喜欢的东西filter,map,flatmap,运营商+ -对非懒藏品时都创建副本.当在a上使用时,Sequence他们会在访问时将值修改为集合,并继续保持惰性(导致另一个Sequence).虽然一Sequence,调用的内容,如toList,toSet,toMap会导致所取得的最终副本.通过命名约定几乎任何开头的东西to都是复制.

换句话说,大多数操作员返回与您开始时相同的类型,如果该类型是"只读",那么您将收到一份副本.如果该类型是懒惰的,那么您将懒惰地应用更改,直到您完整地请求集合.

有些人出于其他原因需要它们,例如并行处理.在这些情况下,最好是查看专为此目的而设计的高性能集合.并且只在这些情况下使用它们,而不是在所有一般情况下.

在JVM世界中,很难避免与需要标准Java集合的库互操作,并且转换到这些集合或从这些集合转换会给不支持公共接口的库增加许多痛苦和开销.Kotlin提供了良好的互操作性和缺乏转换,并通过合同进行了只读保护.

因此,如果您无法避免需要不可变集合,Kotlin可以轻松处理JVM空间中的任何内容:

此外,Kotlin团队正在为Kotlin本地开发Immutable Collections,可以在这里看到:https: //github.com/Kotlin/kotlinx.collections.immutable

还有许多其他的收集框架可以满足所有不同的需求和限制,Google是您寻找它们的朋友.Kotlin团队没有理由需要为其标准库重新发明它们.你有很多选择,他们专注于不同的事情,如性能,内存使用,非拳击,不变性等."选择是好的"...因此其他一些: HPCC,HPCC-RT,FastUtil,Koloboke,Trove等......

甚至还有像Pure4J那样的努力,因为Kotlin现在支持Annotation处理,也许可以为Kotlin提供类似理想的端口.


mfu*_*n26 8

Kotlin 1.0在标准库中不会有不可变的集合.但它确实具有只读和可变接口.没有什么能阻止你使用第三方不可变集合库.

Kotlin List界面中的方法"仅支持对列表的只读访问",而其MutableList界面中的方法支持"添加和删除元素".然而,这两者都只是接口.

Kotlin的List接口在编译时强制执行只读访问,而不是将此类检查推迟到运行时java.util.Collections.unmodifiableList(java.util.List)(如"返回指定列表的不可修改的视图... [where]尝试修改返回的列表...导致UnsupportedOperationException" 它不会强制执行不变性.

请考虑以下Kotlin代码:

import com.google.common.collect.ImmutableList
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith

fun main(args: Array<String>) {
    val readOnlyList: List<Int> = arrayListOf(1, 2, 3)
    val mutableList: MutableList<Int> = readOnlyList as MutableList<Int>
    val immutableList: ImmutableList<Int> = ImmutableList.copyOf(readOnlyList)

    assertEquals(readOnlyList, mutableList)
    assertEquals(mutableList, immutableList)

    // readOnlyList.add(4) // Kotlin: Unresolved reference: add
    mutableList.add(4)
    assertFailsWith(UnsupportedOperationException::class) { immutableList.add(4) }

    assertEquals(readOnlyList, mutableList)
    assertEquals(mutableList, immutableList)
}
Run Code Online (Sandbox Code Playgroud)

请注意如何readOnlyListList和方法,如add不能得到解决(并不会编译),mutableList可以自然突变,并addimmutableList(从谷歌番石榴),也可以在编译时间内解决,但会引发在运行时异常.

除了最后一个断言之外,所有上述断言都会通过,Exception in thread "main" java.lang.AssertionError: Expected <[1, 2, 3, 4]>, actual <[1, 2, 3]>.即我们成功地改变了只读状态List!

请注意,使用listOf(...)而不是arrayListOf(...)返回有效不可变列表,因为您无法将其强制转换为任何可变列表类型.但是,使用List变量接口不会阻止将MutableList其分配给它(MutableList<E>扩展List<E>).

最后,请注意Kotlin(以及Java)中的接口无法强制实现不可变性,因为它"无法存储状态"(请参阅接口).因此,如果您想要一个不可变的集合,您需要使用类似Google Guava提供的集合.


另见ImmutableCollectionsExplained·google/guava Wiki·GitHub