複数の値を収めるコンテナタイプの型はプログラムに欠かせません。今回はコンテナタイプの序として配列(Array型)を取り上げていこうと思います。
後に取り上げるコレクションとは違う部分もありますので、混乱してしまわないためにも配列は一応押さえておきたいところです。
「配列」というとJavaScriptやPHPに馴染みのある方は名前としては入りやすいかも知れませんが、その仕様は異なる部分も多いので注意が必要です。
配列の作成
配列を作成する方法は大きく分けて2種類。
- 配列の要素となる値を直接指定して作成する
- 要素数を指定し、ラムダ式を使って作成する
このどちらかの方法をとります。
arrayOf関数で配列を作成する
val ary = arrayOf("朝","昼","晩","カレー")
基本的にはarrayOf関数を使って作成します。
関数なので最初の文字は小文字です。他の方法をとった場合は最初が大文字のことも多く、忘れやすいポイントなので押さえておいてください。
この他にもKotlinでは「〇〇Of」の形でインスタンスを作成する場面が多くあります。
Arrayコンストラクタで作成する
要素数とラムダ式を設定して作成することもできます。こちらはArrayクラスのコンストラクタなので、最初は大文字です。
val ary = Array(5){it} //[0,1,2,3,4]
この場合、Arrayの第一引数には要素数、ラムダ内のitには0からの整数が入ります。
作成される配列は[0,1,2,3,4]です。
val ary = Array(5){it*it} //[0,1,4,9,16]
ラムダ式なのでitを変化させることも可能です。これだと整数を2乗した[0,1,4,9,16]の配列ができます。
arrayOfNullsでnull埋め配列を作成する
arrayOf関数の仲間としてもう1つ紹介しておきましょう。
個別の値は後から入れる予定で要素数だけを指定したい場合は、arrayOfNulls関数を使って値がnullの配列を作成することもできます。
val ary: Array<Int?> = arrayOfNulls(5) //[null,null,null,null,null]
この場合、変数の明示的な型指定が必要になるので注意してください。
配列の型パラメータ
このようにして作成された変数の型は「Array<型名>」という表記になります。最初の例で作った配列はArray<String>型です。
この<>内を型パラメータと呼び、配列に収まっている値の型を表します。
また違う型が混在している配列の場合、その型はArray<Any>型となります。
このAnyは「なんでもアリ」の便利な型のように思えますが、個別の値に対して何らかの処理をするのであれば、その型が何の型なのか判別しないと基本的にメソッドが使えない、null許容型にも似た性質のものなので、使う場合は注意が必要です。
配列の操作
それではここから、作成した配列に対しての基本的な操作方法に移りたいと思います。
import java.util.*
fun main() {
var ary = arrayOf("朝","昼","晩","カレー")
println(ary[3]) //カレー
ary[0] = "来週"
ary+="うどん"
println(ary.size) //5
println(Arrays.toString(ary)) //[来週, 昼, 晩, カレー, うどん]
}
配列内の値を指定する – インデックス番号(添え字)
配列内の個別の値を指し示すには配列のインデックス番号(添え字)を指定します。ここは他の言語に触れたことがある方はお馴染みではないでしょうか。0始まりな点も他の多くの言語と同じです。
5行目ではary[3]
と指定することで、配列内の4番目に入っている値を指定して標準出力しています。
ただ要素数の指定が間違っていた場合、この時点で例えばary[4]
を指定した場合は例外エラーになりますので注意です。
//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
例外エラーを回避する
もしこのArrayIndexOutOfBoundsExceptionを回避したい場合、インデックスアクセス用のメソッドを使うという手もありますのでご紹介しましょう。getOrElseとgetOrNullです。
getOrElse
println(ary.getOrElse(4){"インデックス${it}は範囲外です"}})
//インデックス4は範囲外です
getOrElseは配列のインスタンスから呼び出し、2つの引数を取ります。第一引数では配列のインデックス番号を指定し、第二引数でそのインデックス番号が無かった場合の処理をラムダ式で記述します。
この場合、インデックス4番がaryに無ければ文字列を返します。ラムダ式の引数には指定したインデックス番号が送られているのが分かります。
getOrNull
println(ary.getOrNull(4)?:"無理") //無理
getOrNullはgetOrElseと同じく配列から呼び出しますが、引数はインデックス番号のみです。
指定した番号が配列に無ければnullを返すので、当然この関数の実行結果の型はnull許容型です。ここではエルビス演算子を使用して、値がnullであったときの出力を設定しています。
配列の要素を変更する
配列は後から要素を変更することができます。
ary[0] = "来週"
変更するには単純にインデックス番号を指定して、そこに新たな値を代入しましょう。
変更ではなく、既にある配列に要素を追加するのであれば、
ary += "うどん"
のように+=演算子を使って追加します。
配列の要素数を出力する – sizeプロパティ
println(ary.size) //5
次の行では配列の要素数を出力しています。配列の場合は配列.size
です。Javaのlengthと同じように、プロパティなので()は必要ありません。
配列を標準出力する – Arrays.toString()
配列はそのままprintln関数に渡しても、期待したような出力が得られません。
println(ary)
//[Ljava.lang.String;@19dfb72a
配列の中身を標準出力するのであれば、
println(Arrays.toString(ary))
のように、Arrays.toString()
の引数に標準出力したい配列を渡します。このArraysはjava.utilライブラリの中に定義されているので、使う場合はインポートする必要があります。
IntelliJなどであれば、記述した時点でインポートするかどうかのダイアログが出てくるので、Alt+Enterでインポートしましょう。
配列のループ処理
コンテナタイプの型と切っても切れないループ処理。Kotlinのforの文法はPythonにも似ていて、非常に簡潔にfor文が書けます。
今回の記事では詳細な説明は避け、配列内の要素を順番に出力する、ごく基本的な構文の紹介に絞って解説しておきます。
for
for(i in ary){println(i)}
//朝
//昼
//晩
//カレー
for (値が入る変数 in 配列など){処理内容}
配列が入った変数ary
から、1つずつ要素を取り出してローカル変数「i」に代入し、処理ブロックに送ります。
「i」の部分は自由に名前が付けられますが、ことループ処理のローカル変数は、このようにごく短い変数名も多く見かけます。
JavaやJavaScriptに慣れている方は、forループといえばこちらの構文が思い浮かぶかもしれません。
for(let i=0; i<ary.length; i++){console.log(ary[i])}
しかしこの構文はKotlinでは不可です。もしループする回数を可変にするのであれば、
for(i in 0..3){println(ary[i])}
in
の後にRange型を置いてループさせましょう。
forEach
ary.forEach({i->println(i)})
こちらはforEach文。出力結果は上記for文と同じです。形を見ると分かるように、波括弧{}の中身はラムダ式になっています。
復習になりますが、ラムダ式は丸括弧()の外側に出すことができ、
ary.forEach(){i->println(i)}
丸括弧は空であれば省略でき、
ary.forEach{i->println(i)}
さらに引数が1つであればそれも省略して、「it」で参照できます。
ary.forEach{println(it)}
配列など.forEach{ラムダ式}
forEachは呼び出し元の配列から1つずつ要素を取り出し、そのままラムダ式に引数「it」として渡します。
おさらい
今回は配列の作成と処理を軽く解説してみました。
- 作成方法
- 値の指定、変更、追加
- 要素数の取得と標準出力
- forとforEach
次回はKotlinのコンテナタイプの主役となるであろう「コレクション」について。