はじめに
今回はKotlinのListについて書きます
Collectionまとめて書こうと思ったら、量がすごくなりそうだったので、Listだけです。
kotlinではreadOnlyのListとmutableのListが存在しています。
FizzBuzzを書いたときは勘違いしていたのですが、immutableのListはまだないようです。
関連サイト
-
Kotlin公式HP
https://kotlinlang.org/ -
CollectionsのRefarence
https://kotlinlang.org/docs/reference/collections.html -
ListのMethod
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html
Listの共通的なおはなし
なんとなく全Listに言えるようなことをつらつらまずは書いていきます。
- Indexは0オリジンです
- 要素の取得の仕方はgetメソッドを使うのと[]で配列のように取得する方法の両方を使えることが出来ます
list.get(0)
list[0]
- ラムダ式はJavaのようにstream変換せずにList型のまま使用出来るのもあります
- streamへの変換は可能なので、中間処理が面倒くさいやつはこっちで書くのもないとは言えない気がします。混ぜるな危険という気もしますし、どっちが良いのかは分かりません。
// 引数が1つの場合はitで取得可能
list.forEach { print(it) }
list.stream().map { it *2 }.collect(Collectors.toList())
mutableList
それでは、まずはmutableListについて見ていきます。
object Main {
@JvmStatic
fun main(args: Array<String>) {
val list: MutableList<Int> = mutableListOf()
list.add(1)
list.add(2)
print(list)
list.add(3)
print(list)
}
}
あんまり語ることもないですが、もちろん中身をいじれます。
今回Listの型を明示的にしていますが、Listの初期化時に型が分からない場合は明示する必要があります。
型を書かなくて良いケースは初期化時に型が推測出来る場合のみです。
val list= mutableListOf(1,2,3)
こんな感じですね。
初期化で値を入れない場合の宣言はこんな感じでも大丈夫です。
val list = mutableListOf<Int>()
分かればよかろうです。
ReadOnlyのList
次はReadOnlyのお話です。
ReadOnlyなので、初期化する際に中身を決定してあげなければなりません。
object Main {
@JvmStatic
fun main(args: Array<String>) {
val list= listOf(1,2,3)
print(list)
}
}
こちらは型が確実に推測できるため、大体型を書かずにすみます。
MutableList -> Listの変換は可能ですが、逆の変換は出来ないので注意が必要です。
val list= mutableListOf(1,2,3)
val list2 : List<Int> = list
val list3 : MutableList<Int> = list2
list2はエラーになりませんが、list3はエラーになります。
まぁ、当たり前と言えば当たり前ですが、いつかどこかでやらかし勢になりそうな気がしないでもないです。
readOnlyのListについては副作用のあるメソッドは使用出来ませんが、副作用がないものについては大抵可能なようです。
使えるメソッドはIDEとかで見たほうが早いので、そこらへんはそっちでよろしくお願いします。
Listでやれることを少し(sort filter map)
ここからはListでやれることを少し書いていこうと思います。
本来ならある程度グループ分けして全部思ったんですが、多すぎて諦めました。
そこで、よく使いそうなsort、filter、mapの基本的な使い方について書いていきます。
他にも色々あるようですが、そういうのはおいおいでいいかなと思ってます。
さらに知りたい方は公式見てください。
sortのおはなし
簡単なソートはsortメソッドを使えば大丈夫です。
sortedも同様の動作で副作用無しです(ソート結果が返却される)。
list.sort()
list.sorted()
こちらからソート条件を指定したい場合はsortWithメソッドを使います。
list.sortWith(Comparator {
a,b -> a.compareTo(b)
})
Comparatorを渡してやるので、Javaのstreamのsortと同じような感じがしますが、Javaの場合はstreamの中間処理なので繋げて複数のソートをすることが出来て、こちらは副作用のあるメソッドというだけで、複数は繋げることが出来ないため注意が必要です。
また、sortについては比較してソートさせる方法だけではなく、優先度を返却することでソートさせるsortByメソッドがあります。
(優先度という表現が正しいかは分かりません)
list.sortBy { it * -1}
この場合は優先度が数字を反転させた形になるので、この場合は逆順でソートされます。
色々用途は思い浮かぶので有用な使い方が出来そうです。
降順でのソートはデフォルトで用意されるので、そんなことをしなくても大丈夫なんですが。
list.sortedDescending()
条件を付けることも可能です。
これは優先度の降順です。
下のやつだと結局は昇順になります。
list.sortedByDescending{it * -1}
filterのおはなし
list.filter{it == 1}
list.filterIndexed{index , item -> item == 1}
上が普通のフィルターで下がIndex付きのフィルターです。
filterIndexedToを使えばフィルターした結果を他のリストに入れることも出来ます。
val list2 = mutableListOf<Int>()
list.filterIndexedTo(list2 , { index, item -> item == 1})
filterにはnotで条件付けが出来るメソッドがあり、地味便利です。
混ざると分からなくなりそうな気もするので、notとするかしないかはチームで話し合ったほうがいい案件かもしれません
list.filterNot { it % 2 == 0 }
これで奇数が取得できます。
Null排除に関してはさらに便利なのが用意されていて
list.filterNotNull()
なんてこれだけで可能となります。
いちいち == nullって書かなくていいので、この場合はこのメソッドを使って楽しましょう。
mapのおはなし
val list2 = list.map { it.toString() }
基本的には簡単です。
Javaでは(確か)出来なかったと思いますが、Index付きで引数を受け取ることも可能です。
val list2 = list.mapIndexed { index, i -> i.toString() }
Indexが必要って場面は意外と多いんでありがたい話です。
ついでにreturn値がnullの場合に排除というのがいっぺんにも出来ます。
list.mapNotNull { it }
うん便利。
val list= mutableListOf(1,2,3,null)
val list2 = list.mapNotNull { it.toString() }
print(list2)
どうでもいいかもしれませんが、この結果を見たら[1,2,3]
じゃなくて[1, 2, 3, null]
だってのでちょっとびっくりしました。
最後に
とりとめなくつらつらと書いてきましたが、簡単に便利にList作って操作できるのでありがたいです。
上で書いたように全部書いているわけではないので、他の機能についても勉強していきます。もしかしたら追加で書くかもしれません。
今のところはほかのCollectionsの機能については書いていく予定ではありますが。
動かしながら書いているけど、間違いがないかだけが心配。