Kotlin大好きな人向けなCollectionのstdlibメソッドを掘り出してみた

これはQiita Kotlin Advent Calendar 10日目の記事です。

qiita.com

これマニアックなんじゃね?Kotlin大好きな人向けなんじゃね?ってstdlibにあるIterable/Collection/List/Set/Mapのメソッドを独断と偏見で挙げてみようと思います!

Collection - Kotlin Programming Language

想定読者

  • KotlinのCollectionのstdlibメソッドもっと知りたい人
  • 一旦はさすがです!って褒めてくれる人

環境

Kotlin 1.3.11で使えるメソッドにしています。全メソッドPlaygroundで動作確認済みです。

distinct

説明: 重複削除したListを作る

distinct - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/HJnYskugV

fun main() {
    val list = listOf(1,1,1,3,5)
    println("List: $list") // List: [1, 1, 1, 3, 5]
    println("Result: ${list.distinct()}") // Result: [1, 3, 5]
}

感想: かー毎回Setに詰め込んでたね。それでListが欲しい場合は、toListしてたね。さらに順番が必要なら色々頑張ってたね。便利😊

intersect

説明: 両方のCollectionに入っている要素をSetにして返す

intersect - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/SkQkak_eE

fun main() {
    val list1 = listOf(1,1,1,3,5)
    val list2 = listOf(3,4,1)
    println(list1.intersect(list2)) // [1, 3]
}

感想: 知らなかったら、filterとかcontainsメソッドなどで泣きながら書いてたと思う。

union

説明: Collectionをがっちゃんこする。戻り値はSet

union - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/rykBje_lV

fun main() {
    val list1 = listOf(1,1,1,3,5)
    val list2 = listOf(3,4,1)
    println(list1.union(list2)) // [1, 3, 5, 4]
}

感想: intersectと同じ感想

onEach

説明: 渡した引数のactionを全ての要素に実行し、レシーバーを返す

onEach - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/HyrGyxugE

fun main() {
    val list = listOf(1,1,1,3,5)
    list.onEach {
        println("Log: $it")
    }.filter {
        it > 3
    }.forEach {
        println("Result: $it")
    }
}

結果

Log: 1
Log: 1
Log: 1
Log: 3
Log: 5
Result: 5

感想: forEachして、そのまま何かしたい!って時にまたレシーバーを書いてたけど、これ使えば全部繋げられるじゃん。便利じゃん。onEachWithIndexとか欲しくなりそう。

partition

説明: Collectionの要素が引数の条件にマッチした要素をPairのfirstのListに。マッチしない要素をsecondのListに分割する

partition - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/HJgvexugN

fun main() {
    val list = listOf(1,1,1,3,5)
    println(list.partition { it >= 3 }) // ([3, 5], [1, 1, 1])
}

感想: 分割が必要な時、頑張らなくてもいいね!

requireNoNulls

説明: 要素にnullがないことを担保する。もし、nullがあればIllegalArgumentException

requireNoNulls - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/SJ3VMlul4

fun main() {
    val list: List<Int?> = listOf(1,2,4)
    val listNoNulls: List<Int> = list.requireNoNulls()
}

感想: requireNotNullのCollection版って感じ。nullがないことが前提条件のメソッドとかで利用できそう。(特に気にもせずに無心でfilterNotNullするかもだが。。。)

unzip

説明: PairのArrayに対し、firstの値だけのListとsecondの値だけのListをPairとして返す。

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/unzip.html

サンプルコード:

https://pl.kotl.in/ryYFNedx4

fun main() {
    val array = arrayOf(1 to "foo", 2 to "bar", 3 to 5)
    println(array.unzip()) ([1, 2, 3], [foo, bar, 5])
}

感想: ちょっと限定的すぎる?🤔いや、こういうのいいですよねきっと!

windowed

説明: Collectionをsizeの要素数のListを作る。次のListはstep分ずれたものからスタートする。

ごめんなさい。どう英訳すれば一番わかりやすいのかすらわからない。以下が原文。

Returns a list of snapshots of the window of the given size sliding along this collection with the given step, where each snapshot is a list.

windowed - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/r13a_gdxN

fun main() {
    val list = listOf(0,1,2,3,4,5,6,7,8,9)
    println(list.windowed(size = 5, step = 3)) // [[0, 1, 2, 3, 4], [3, 4, 5, 6, 7]]
    println(list.windowed(size = 5, step = 3, partialWindows = true)) // [[0, 1, 2, 3, 4], [3, 4, 5, 6, 7], [6, 7, 8, 9], [9]]
}

partialWindowsがtrueだった場合、sizeに足りてないものも含む。

感想: ちょっと置いていかれたメソッド。これが便利なんだ!というくらいKotlinを使いこなしたい・・・

zipWithNext

説明: Listの隣り合った要素をListのPairとして返す

zipWithNext - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/r1cjdxOlE

fun main() {
    val list = listOf(0,1,2,3,4,5,6,7,8,9)
    println(list.zipWithNext()) // [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]
    println(list.zipWithNext { a, b -> a + b }) // [1, 3, 5, 7, 9, 11, 13, 15, 17]
}

感想: transformを渡せば、数列とかで便利かも?あとは次の値を見て何かするような処理とかでもいいかも。