Kotlinのリストと配列の違い
1. 概要
このチュートリアルでは、比較します配列
2. 配列 対。 リスト
2.1. データ構造
データ構造の観点から、Kotlinコンパイラは配列をコンパイルします
たとえば、簡単な例を考えてみましょう。
val cities = arrayOf("Tehran", "Sari", "Neka")
Kotlinコンパイラ( kotlinc )は、これをバイトコードにコンパイルします。 javap を使用して表示すると、次のようになります。
0: iconst_3
1: anewarray #8 // class java/lang/String
anewarray opcodeは、参照型の配列を作成します。 また、iconst_3は整数3をオペランドスタックにプッシュします。 後で、 anewarray 命令は、この整数を配列の長さとして使用します。
一方、リスト
に加えて配列リスト
Kotlinの配列とは対照的に、 Kotlinのリストのメモリ表現は、完全に具体的な実装に依存するため、変化する可能性があります。
2.2. 可変性
Kotlinの配列は常に変更可能です。これは、各セグメントの値を新しいものに置き換えることができるためです。
cities[0] = "Berlin"
ただし、配列は固定サイズであるため、配列に新しい値を追加したり追加したりすることはできません。
一方、 リスト
可変性が必要な場合は、 MutableList
val colors = mutableListOf("Blue") // [Blue]
colors[0] = "Green" // replace: [Green]
colors.add(0, "Red") // prepend: [Red, Green]
colors.add("Blue") // append: [Red, Green, Blue]
とは対照的に配列
2.3. 一般的な分散
ジェネリックに関する分散の概念は、同じベースタイプと異なるタイプパラメーターを持つジェネリックタイプが互いにどのように関連するかを決定します。
たとえば、StringがKotlinのAnyのサブタイプであることは誰もが知っています。 それを考えると、 リスト
public interface List<out T> : Collection<T> {
override fun iterator(): Iterator<T>
public operator fun get(index: Int): T
// omitted
}
タイプ引数Tは常にoutの位置で使用されるため、リスト
val colors = listOf("Red")
val colorsAsAny: List<Any> = colors // this works
共分散のため、ここでは次の値を割り当てています。 リスト
一方、同じことは当てはまりません MutableList
public interface MutableList<T> : List<T>, MutableCollection<T> {
override fun add(element: T): Boolean
override fun remove(element: T): Boolean
// omitted
}
だから MutableList
val colors = mutableListOf("Red")
val colorsAsAny: MutableList<Any> = colors
不変性のため、上記のスニペットはコンパイルすらしません。 非常に似ています MutableList
val colors: Array<Any> = arrayOf<String>("Red")
これらのタイプの違いは、特にJavaのバックグラウンドから来ている場合、混乱を招く可能性があります。 Javaでは、ジェネリック型は不変であり、配列は共変です。
2.4. 特殊なプリミティブ
Kotlinには、プリミティブ型の配列を作成するための特別な関数があります。
val bytes = byteArrayOf(42)
val shorts = shortArrayOf(42)
val ints = intArrayOf(42)
val longs = longArrayOf(42)
val floats = floatArrayOf(42.0f)
val doubles = doubleArrayOf(42.0)
val chars = charArrayOf('a')
val booleans = booleanArrayOf(true)
これは主に、JVMにそのような配列を作成および操作するための特別なオペコードがあるためです。
0: iconst_1
1: newarray byte
ここで、バイトコードは newarray opcode( anewarray ではなく)を使用してバイトの配列を作成します。 つまり、配列はプリミティブデータ型の表現を最適化しており、パフォーマンスに敏感な場合に適しています。
一方、Kotlin標準ライブラリのリストには、プリミティブ用に最適化されたバージョンはありません。
2.5. その他の微妙な違い
Javaとの良好な相互運用性を実現するために、Kotlinは一部のJavaタイプを特別に扱います。 このようなタイプは、Javaから「そのまま」ロードされるのではなく、対応するKotlinタイプにマップされます。 すなわち、 リスト
これらすべてに加えて、2つの間にさらに微妙な違いがいくつかあります。 たとえば、“ ==” 演算子は、配列に参照の同等性を使用し、リストにコンテンツの同等性を使用しています。
println(intArrayOf(1) == intArrayOf(1)) // false
println(listOf(1) == listOf(1)) // true
3. 結論
この記事では、Kotlinの配列とリストの違いを列挙しました。 要約すると、配列は要素の固定サイズのシーケンスであり、ジェネリックに関しては可変で不変であり、より最適化されたプリミティブバージョンが付属しています。 さらに、アレイに対するJVMの特別な処理を利用しています。
一方で、 リスト