Kotlin不変コレクション

1. 前書き

このチュートリアルでは、* Kotlinで不変のコレクションを作成する方法を見ていきます*。
最初に、Kotlinが標準として提供するものだけでなく、不変性の種類を探ります。 次に、GoogleのGuavaライブラリを活用して真に不変のコレクションを作成する方法を見ていきます。*
別の方法として、* Kotlinの* Kotlinx Immutable Collections Library *も参照します。

2. 依存関係

不変コレクションを作成する前に、Guavaと不変コレクションライブラリをインポートする必要があります。

2.1. メーベン

<!-- https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-collections-immutable -->
<dependency>
    <groupId>org.jetbrains.kotlinx</groupId>
    <artifactId>kotlinx-collections-immutable</artifactId>
    <version>0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>27.1-jre</version>
</dependency>
<repository>
    <snapshots>
        <enabled>false</enabled>
    </snapshots>
    <id>kotlinx</id>
    <name>bintray</name>
    <url>https://dl.bintray.com/kotlin/kotlinx</url>
</repository>

2.2. Gradle

repositories {
    maven {
        url "https://dl.bintray.com/kotlin/kotlinx"
    }
}

// https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-collections-immutable
compile group: 'org.jetbrains.kotlinx', name: 'kotlinx-collections-immutable', version: '0.1'
// https://mvnrepository.com/artifact/com.google.guava/guava
compile group: 'com.google.guava', name: 'guava', version: '27.1-jre'

3. 不変性の種類

始める前に、*コレクションが持つことができるさまざまなタイプの不変性を見てみましょう:*
  1. * Mutable * –リストの内容は自由に変更できます

  2. 読み取り専用 –コレクションの内容は、
    かわった。 ただし、基になるデータは変更できます

  3. * Immutable * –コレクションの内容を変更することはできません

    不変コレクションには、プログラミングで多くの用途があります。 たとえば、競合状態に陥るリスクなしに、異なるスレッド間でそれらを自由に共有できます。 また、*不変のコレクションの実装は、可変の代替よりも常にメモリ効率が高い*。
    さらに、Immutableコレクションの使用は、*優れた防御プログラミング手法*であり、データに不要な変更を加えないようにします。

4. コトリンコレクション

  • Kotlinでは、_List_などのすべての不変コレクションは、デフォルトではコンパイル時読み取り専用*であり、不変ではありません。 定義されたインターフェイスはコレクション内のデータを変更するメソッドをサポートしていませんが、基礎となるデータは変更できます。

    読み取り専用の_List_を変更して、これを実証しましょう。
@Test
fun givenReadOnlyList_whenCastToMutableList_checkNewElementsAdded(){

    val list: List<String> = listOf("This", "Is", "Totally", "Immutable")

    (list as MutableList<String>)[2] = "Not"

    assertEquals(listOf("This", "Is", "Not", "Immutable"), list)

}
上記の例では、新しい__List __を作成し、__ list __variableに割り当てます。 デフォルトでは、Kotlinのhttps://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html[_List_ interface]は読み取り専用であり、新しい要素を追加することはできません。リスト。 ただし、__List __をa _MutableList_にキャストすることにより、_add_メソッドを使用して新しい要素を自由に追加できます。

5. グアバ

*絶対的な不変性のために、https://github.com/google/guava/wiki/ImmutableCollectionsExplained [Guavaの不変コレクションのセット]を使用できます。* Guavaは、Guhttps:// githubを含む多くのJavaコレクションの不変バージョンを提供します。 com / google / guava / wiki / ImmutableCollectionsExplained#Details [__ ImmutableList、ImmutableSet __and] __https://github.com/google/guava/wiki/ImmutableCollectionsExplained#Details [ImmutableMap] .__
ImmutableList.ofメソッドを使用して、アクションのImmutableListを見てみましょう:*
@Rule
@JvmField
var ee : ExpectedException = ExpectedException.none()

@Test
fun givenImmutableList_whenAddTried_checkExceptionThrown() {

    val list: List<String> = ImmutableList.of("I", "am", "actually", "immutable")
    ee.expect(UnsupportedOperationException::class.java)
    (list as MutableList<String>).add("Oops")

}
この例では、_MutableList_へのキャストを使用しても、リストが突然変異に抵抗することがわかります。 *新しい要素を受け入れるのではなく、実行時に__UnsupportedOperationException __がスローされます。*
Guavaは、不変リストをインスタンス化する代替方法も提供します。

5.1. のコピー

次に、以前に作成した変更可能なものからfrom_ImmutableList_をインスタンス化する方法を見てみましょう。 *これを実現するために、_copyOf_メソッドを利用できます*。このメソッドは引数として別のコレクションを取ります。
@Rule
@JvmField
var ee : ExpectedException = ExpectedException.none()

@Test
fun givenMutableList_whenCopiedAndAddTried_checkExceptionThrown(){

    val mutableList : List<String> = listOf("I", "Am", "Definitely", "Immutable")

    (mutableList as MutableList<String>)[2] = "100% Not"

    assertEquals(listOf("I", "Am", "100% Not", "Immutable"), mutableList)

    val list: List<String> = ImmutableList.copyOf(mutableList)

    ee.expect(UnsupportedOperationException::class.java)

    (list as MutableList<String>)[2] = "Really?"

}
ここでは、_listOf_メソッドを使用して完全に変更可能なリストを作成します。 次に、__ copyOf __methodを使用して、不変のものを作成します。 最後に、要素が_ImmutableList_に追加されると、コードが例外をスローすることがわかります。

5.2. 便利なビルダー

最後に、不変のコレクションを構築するためにGuavaが提供する便利なビルダーを見てみましょう。 この例では、__ ImmutableSetを作成します。 __ ** https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/collect/ImmutableSet.Builder.html [_ImmutableSet.B_] __https://google.github。 io / guava / releases / snapshot / api / docs / com / google / common / collect / ImmutableSet.Builder.html [uilder] __は、新しい単一要素と他のコレクションのコピーを追加するためのすべての基本的なメソッドを提供します。**
@Rule
@JvmField
var ee : ExpectedException = ExpectedException.none()

@Test
fun givenImmutableSetBuilder_whenAddTried_checkExceptionThrown(){

    val mutableList : List<String> = ArrayList(listOf("Hello", "Baeldung"))
    val set: ImmutableSet<String> = ImmutableSet.builder<String>()
      .add("I","am","immutable")
      .addAll(mutableList)
      .build()

    assertEquals(setOf("Hello", "Baeldung", "I", "am", "immutable"), set)

    ee.expect(UnsupportedOperationException::class.java)

    (set as MutableSet<String>).add("Oops")

}
上記の例では、__ ImmutableSet __of __Strings __using Guavaの___ ImmutableSet.Builder __classを構築します。 最初に、ビルダーの_addAll_メソッドを使用して_mutableList_のコンテンツを追加する前に、_add_メソッドを使用していくつかの*単一の__String__sを追加します。
内容を検証した後、予想どおり、さらに要素を追加しようとすると例外がスローされることがわかります。

6. Kotlinx不変コレクションライブラリ

Kotlinのコレクションの読み取り専用の性質に対するJetBrainの答えは、https://github.com/Kotlin/kotlinx.collections.immutable [Kotlinx Immutable Collections Library]です。 KICL * Kotlinの不変のコレクションインターフェイスと実装プロトタイプを提供します。*
KICLは、グアバの2.6MBのほんの一部に収まり、アプリケーションにわずかな不変性のみが必要な場合に、グアバに代わる軽量の代替品を提供します。
このライブラリの動作を簡単に見てみましょう。
@Rule
@JvmField
var ee : ExpectedException = ExpectedException.none()

@Test
fun givenKICLList_whenAddTried_checkExceptionThrown(){

    val list: ImmutableList<String> = immutableListOf("I", "am", "immutable")

    list.add("My new item")

    assertEquals(listOf("I", "am", "immutable"), list)

}
Kotlinxの不変のコレクションライブラリは、Guavaのコレクションとは少し異なる動作をします。 上記でわかるように、* _ UnsupportedOperationException_をスローするのではなく、_ImmutableList ._ *に追加された新しい要素はありません。

7. 結論

この記事では、不変コレクションの観点からKotlinが提供するものに注目しました。
次に、GoogleのGuavaが提供できる不変コレクションと、Kotlinx Immutable Collection Libraryを詳しく調べました。
すべてのコードスニペットはhttps://github.com/eugenp/tutorials/tree/master/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/immutable[over on GitHub。]にあります。