Edit Page

コレクション(ツアー)

プログラムをする時には、データを何らかの構造を持ったグループにグルーピングして後の処理に備えるのが便利な事がしばしばあります。 Kotlinはまさにこの用途のために、コレクションというものを提供します。

Kotlinはアイテムをグルーピングするのに以下のコレクションが使えます:

コレクションの種類 説明
リスト 順番のある要素のコレクション
セット(集合) ユニーク(一意)で順番の無い要素のコレクション
マップ キーと値のペアのセットのようなもの。キーはユニークで、各キーはただ一つの値に関連づけされている

これらの各コレクションに、mutableと読み取り専用(read only)の二種類があります。

リスト

リストは要素を追加された順番に保持します。重複した要素も追加出来ます。

読み取り専用リスト (List)を作るには、 listOf() 関数を使います。

mutableなリスト(MutableList)を作るには, mutableListOf()関数を使います。

リストを作るに際し、Kotlinは格納される要素の型を推論出来ます。 型を明示的に宣言したい時は、リストの宣言のあとに角括弧<>で型を指定します。

fun main() { //sampleStart // 読み取り専用リスト val readOnlyShapes = listOf("triangle", "square", "circle") println(readOnlyShapes) // [triangle, square, circle] // Mutableなリストに明示的な型指定があるケース val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle") println(shapes) // [triangle, square, circle] //sampleEnd }

意図せぬ変更をまぎれこませない為に、mutableなリストから、その読み取り専用のviewを作る事が出来ます。それはList型変数に代入することで得られます:

    val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
    val shapesLocked: List<String> = shapes

これはまた、 キャスト(casting)とも呼ばれます。

Listは順番があるコレクションなので、要素にアクセスする時にはそのインデックスを用いたインデックスアクセスの演算子 []を使います:

fun main() { //sampleStart val readOnlyShapes = listOf("triangle", "square", "circle") println("このリストの最初の要素は: ${readOnlyShapes[0]}") // このリストの最初の要素は: triangle //sampleEnd }

リストの最初の要素を取り出す時は.first()関数を、 最後の要素を取り出す時には.last()関数を使う事が出来ます:

fun main() { //sampleStart val readOnlyShapes = listOf("triangle", "square", "circle") println("このリストの最初の要素は: ${readOnlyShapes.first()}") // このリストの最初の要素は: triangle //sampleEnd }

.first()関数と.last()関数は、 extension関数と呼ばれる関数の例にもなっています。あるオブジェクトのextension関数を呼ぶには、オブジェクトの後ろに . をつけて、 その後に関数名をつなげれば呼ぶ事が出来ます。 extension関数についてもっと知りたければ、Extension関数を参照ください。 ですがこのツアーを続けていくのに必要な事は、単にそれらをどう呼べば良いかだけです。

リストの中に要素がいくつ入っているかを知るには、.count() 関数を使います:

fun main() { //sampleStart val readOnlyShapes = listOf("triangle", "square", "circle") println("このリストには ${readOnlyShapes.count()}個の要素が入っています。") // このリストには 3個の要素が入っています。 //sampleEnd }

ある要素がリストの中にあるかどうかを調べるには、in 演算子を使います:

fun main() { //sampleStart val readOnlyShapes = listOf("triangle", "square", "circle") println("circle" in readOnlyShapes) // true //sampleEnd }

mutableなリストに要素を追加するには.add()関数を、 mutableなリストから要素を削除するには.remove()関数を使います:

fun main() { //sampleStart val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle") // リストに"pentagon"を追加(訳注:ペンタゴンは五角形) shapes.add("pentagon") println(shapes) // [triangle, square, circle, pentagon] // 最初に見つかった"pentagon"をリストから削除 shapes.remove("pentagon") println(shapes) // [triangle, square, circle] //sampleEnd }

セット(集合)

リストが順番があり重複する要素も許すのに対し、セット(Set)は順序なし(unordered)なコレクションで、一意(unique)な要素だけを格納出来ます。

読み取り専用のセットを作るには、(Set)、 setOf()関数を使います。

mutableなセットを作るには、(MutableSet)、 mutableSetOf()関数を使います。

セットを作る時には、Kotlinは格納される要素の型を推論します。 型を明示的に宣言したい時は、セットの宣言の後に角括弧<>をつけて、その中に型を書きます。

fun main() { //sampleStart // 読み取り専用のセット val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry") // mutableなセットを明示的な型指定ありで作るケース val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry") println(readOnlyFruit) // [apple, banana, cherry] //sampleEnd }

この例で、セットはユニークな要素だけを保持する事から、重複しているはずの"cherry"の重複が除去されています。

意図せぬ変更を防ぐために、mutableなセットから読み取り専用のビューをセットにキャストする事で作る事が出来ます:

    val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")
    val fruitLocked: Set<String> = fruit

セットは順序なし(unordered)のコレクションなので、特定のインデックスの要素にアクセスする方法はありません。

セットに含まれる要素の数を得るためには、.count()関数が使えます:

fun main() { //sampleStart val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry") println("このセットには ${readOnlyFruit.count()}個の要素が含まれています") // このセットには 3個の要素が含まれています //sampleEnd }

ある要素がセットの中にあるかどうかは、in 演算子で知る事が出来ます:

fun main() { //sampleStart val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry") println("banana" in readOnlyFruit) // true //sampleEnd }

mutableなセットに要素を追加するには.add()関数を、 要素を削除するには.remove()関数を使います:

fun main() { //sampleStart val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry") fruit.add("dragonfruit") // "dragonfruit"をセットに追加 println(fruit) // [apple, banana, cherry, dragonfruit] fruit.remove("dragonfruit") // "dragonfruit"をセットから削除 println(fruit) // [apple, banana, cherry] //sampleEnd }

マップ

マップはキーと値のペアとして要素を保持するコレクションです。キーを指定する事で対応する値にアクセスする事が出来ます。 マップというのはレストランなどのメニューのようなものと考えると近いかもしれません。 食べたい料理で探すと、対応する価格を知る事が出来ます。 マップは数字のインデックスでは無い何かで値を探したい、という時に便利です。(数字のインデックスならListで良いので)

  • マップのそれぞれのキーはユニークでなくてはいけません。キーがユニークなのでKotlinはあなたが指定したキーでどの値を取り出そうとしているかが判断出来ます。
  • ですが値は重複があっても問題ありません。

読み取り専用のマップ(Map)を作るには、 mapOf()関数を使えば良いです.

mutableなマップ(MutableMap)を作りたければ、 mutableMapOf()関数を使いましょう。

マップを作る時、Kotlinは格納される要素の型を推測してくれる。 もしキーと値の型を指定したいなら、マップの宣言の後に角括弧<>を続けて、この角括弧の中にキーと値の型を掛けば良い。 例えば、MutableMap<String, Int>のような感じ。この場合キーはString型で値はInt型となる。

マップをつくる 一番カンタンな方法は、 キーと値の間にtoを置く、という手法になる:

fun main() { //sampleStart // 読み取り専用のマップ val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100) println(readOnlyJuiceMenu) // {apple=100, kiwi=190, orange=100} // mutableなマップに明示的な型宣言をつけるケース val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100) println(juiceMenu) // {apple=100, kiwi=190, orange=100} //sampleEnd }

意図せぬ変更を防ぐため、mutableなマップから読み取り専用のビューを、Mapへのキャストで取得出来る:

    val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
    val juiceMenuLocked: Map<String, Int> = juiceMenu

マップの値にアクセスするためには、インデックスアクセス演算子 [] にキーを渡せば良い:

fun main() { //sampleStart // 読み取り専用のマップ val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100) println("リンゴジュースの値段は: ${readOnlyJuiceMenu["apple"]}") // リンゴジュースの値段は: 100 //sampleEnd }

マップの中の要素数を得るためには、.count()関数を使えば良い:

fun main() { //sampleStart // 読み取り専用のマップ val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100) println("このマップには${readOnlyJuiceMenu.count()}個のキーと値のペアがある") // このマップには3個のキーと値のペアがある //sampleEnd }

mutableなマップに要素を追加するには.put()関数を使い、 要素を削除するには.remove()関数を使う:

fun main() { //sampleStart val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100) juiceMenu.put("coconut", 150) // キー"coconut"を値150でマップに追加 println(juiceMenu) // {apple=100, kiwi=190, orange=100, coconut=150} juiceMenu.remove("orange") // キー"orange"をマップから削除 println(juiceMenu) // {apple=100, kiwi=190, coconut=150} //sampleEnd }

あるキーがマップに既に含まれているかを調べるには、.containsKey()関数を使う:

fun main() { //sampleStart val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100) println(readOnlyJuiceMenu.containsKey("kiwi")) // true //sampleEnd }

キーや値のコレクショを得るには、keysプロパティや valuesプロパティを使います:

fun main() { //sampleStart val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100) println(readOnlyJuiceMenu.keys) // [apple, kiwi, orange] println(readOnlyJuiceMenu.values) // [100, 190, 100] //sampleEnd }

keysvalues は、オブジェクトの プロパティ(properties) というものの例となっています。オブジェクトのプロパティにアクセスするには、オブジェクトの後ろに.をつけて、 その後ろにプロパティ名を書けばよろしい。

プロパティについては、クラスの章でより詳細に扱います。 ツアーのこの時点では、どうやってプロパティにアクセスするかだけ分かっていれば十分です。

キーや値がマップにあるかをチェックするには、in 演算子を使います:

fun main() { //sampleStart val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100) println("orange" in readOnlyJuiceMenu.keys) // true println(200 in readOnlyJuiceMenu.values) // false //sampleEnd }

コレクションについてより詳しい情報を知りたければ、コレクションを参照ください。

基本型を知り、コレクションをどう管理したらいいかを理解した今、あなたの書くプログラムの中で使える制御フローについて学ぶ時が来ました。

練習問題

練習問題 1

“green”の数字のリストと、“red”の数字のリストがあったとします。 全体でいくつの数字があるかをprintするコードを完成させなさい。

fun main() { val greenNumbers = listOf(1, 4, 23) val redNumbers = listOf(17, 2) // ここにコードを書いてね }
解答例
fun main() {
    val greenNumbers = listOf(1, 4, 23)
    val redNumbers = listOf(17, 2)
    val totalCount = greenNumbers.count() + redNumbers.count()
    println(totalCount)
}

練習問題 2

あなたのサーバーがサポートするプロトコルの集合があるとします。 ユーザーは特定のプロトコルを使う、とリクエストする事とします。 リクエストされたプロトコルがサポートされているかどうかをチェックする以下のプログラムを完成させなさい(isSupportedはBoolean型の値にならなくてはなりません)。

fun main() { val SUPPORTED = setOf("HTTP", "HTTPS", "FTP") val requested = "smtp" val isSupported = // ここにコードを書いてね println("Support for $requested: $isSupported") }
ヒント

リクエストされたプロトコルがいつも大文字になるようにしましょう。 その為には.uppercase()関数が助けになるかもしれません。

解答例
fun main() {
    val SUPPORTED = setOf("HTTP", "HTTPS", "FTP")
    val requested = "smtp"
    val isSupported = requested.uppercase() in SUPPORTED
    println("Support for $requested: $isSupported")
}

練習問題 3

数字の1から3までと、それに対応した英語のスペリングを持つマップを作成せよ。 このマップを用いて、与えられた数字をスペリングに変更するコードを書け。

fun main() { val number2word = // ここにコードを書いてね val n = 2 println("$n is spelt as '${<ここにもコードを書いてね >}'") }
解答例
fun main() {
    val number2word = mapOf(1 to "one", 2 to "two", 3 to "three")
    val n = 2
    println("$n is spelt as '${number2word[n]}'")
}

次回

制御フロー