概要
val list1 = listOf("犬", "狼", "狐")
val list2 = listOf("猫", "虎", "豹")
val list3 = listOf("鷹", "隼", "梟")
上のような複数のList<T>
を, ひとつのList<T>
にまとめる方法についてメモ.
※ 性能については考慮されていません.
※ まとめるのに必須ではありませんが, 要素の重複を弾くケースを考え以下のコードではdistinct()
してます.
1. Listの入れ子にしてflattenする
List<List<T>>
にしてflatten()
する.
個人的にこれが見やすいかなと.
val result = listOf(list1, list2, list3).flatten().distinct()
2. 個々のリストを可変長引数に展開してlistOfでまとめる
Javaでいうところの ...args
.
Kotlinは ...
でなく *
で展開する.
可変長引数化するのに一旦 Array
に変換する必要があるようなので, ちょっとイマイチかも?
val result = listOf(
*list1.toTypedArray(),
*list2.toTypedArray(),
*list3.toTypedArray()
).distinct()
3. plusでaddしていく
うーん...
val result = list1
.plus(list2)
.plus(list3)
.distinct()
ちなみにこのようなコードにした場合, IntelliJではplus
に対して Call chain on collection could be converted into 'Sequence' to improve performance
と警告が出る場合がある.
plus
は毎回Listをnewしているよう. そのためか.
なお, 私の環境ではplus
が4つほど続くと上記警告が出る.
追記
@sikani さんのコメントより.
+
演算子がオーバーロードされているので以下のように書けます。val result = (list1 + list2 + list3).distinct()
plus
が演算子オーバーロードしていることを利用し書き換えたもの.
圧倒的に見やすい! 素敵!
4. SequenceにaddしていきtoListする
3の警告 Call chain on collection could be converted into 'Sequence' to improve performance
に従い, Sequenceにaddしていき最後にListに変換する.
val result = list1
.asSequence()
.plus(list2)
.plus(list3)
.distinct()
.toList()
@sdkei さんのコメントより.
val result = (list1 + list2 + list3).distinct()
これも、パフォーマンスを考えると Sequence にした方がよいですね。
val result = (list1.asSequence() + list2 + list3).distinct().toList()
でもこれだと対称性が美しくないので
val result = (emptySequence<String>() + list1 + list2 + list3).distinct().toList()
…うーん、長い。
5. Sequenceの入れ子にしてflattenする
こちらも @sdkei さんのコメントより.
こっちの方がよさそう。
val result = sequenceOf(list1, list2, list3).flatten().distinct().toList()
1のSequence版.
List<List<String>>
をflatten()
する場合と, Sequence<List<String>>
をflatten()
しtoList()
する場合とで, どの程度性能に違いがあるか気になるところ.
最後に
なにか改善点などがあれば, コメントいただけますと幸いです₍₍(ง˘ω˘)ว⁾⁾