Kotlinのmap()とflatMap()の違い
1. 概要
このチュートリアルでは、Kotlinの map()と flatMap()の微妙な違いについて説明します。
2. map()
map()は、Kotlinの拡張関数であり、次のように定義されています。
fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R>
上に示したように、この関数は、 反復可能
この関数は通常、1対1のマッピング状況で役立ちます。 たとえば、各注文が詳細な購入アイテムとして多くの注文ラインで構成されているとします。
class Order(val lines: List<OrderLine>)
class OrderLine(val name: String, val price: Int)
これで、 Order がある場合、 map()を使用して各アイテムの名前を見つけることができます:
val order = Order(
listOf(OrderLine("Tomato", 2), OrderLine("Garlic", 3), OrderLine("Chives", 2))
)
val names = order.lines.map { it.name }
assertThat(names).containsExactly("Tomato", "Garlic", "Chives")
ここでは、変換していますリスト
val totalPrice = order.lines.map { it.price }.sum()
assertEquals(7, totalPrice)
基本的に、 map()は、次の命令型コーディングスタイルと同等です。
val result = mutableListOf<R>()
for (each in this) {
result += transform(each)
}
map()を使用している場合は、変換部分を作成するだけです。 新しいコレクションの定義、反復、およびそのコレクションへの各変換された要素の追加は、単なる定型コードであり、実装の詳細の一部です。
3. flatMap()
map()とは対照的に、 flatMap() は通常、1対多の関係を平坦化するのに役立ちます。 そのため、その署名は次のようになります。
fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R>
上に示したように、タイプTの各要素をタイプRのコレクションに変換します。 それにもかかわらず、 リスト
例として、注文のコレクションがあり、すべての個別のアイテム名を検索するとします。
val orders = listOf(
Order(listOf(OrderLine("Garlic", 1), OrderLine("Chives", 2))),
Order(listOf(OrderLine("Tomato", 1), OrderLine("Garlic", 2))),
Order(listOf(OrderLine("Potato", 1), OrderLine("Chives", 2))),
)
最初は、どういうわけか変換する必要がありますリスト >>
、これは望ましくありません:
orders.map { it.lines } // List<List<OrderLine>>
平らにする必要があるのでリスト
val lines: List<OrderLine> = orders.flatMap { it.lines }
val names = lines.map { it.name }.distinct()
assertThat(names).containsExactlyInAnyOrder("Garlic", "Chives", "Tomato", "Potato")
上に示したように、 flatMap()関数は、各OrderとそのOrderLinesの間の1対多の関係を平坦化します。
flatMap()に相当する命令型スタイルは次のようなものです。
val result = mutableListOf<OrderLine>()
for (order in orders) {
val transformedList = order.lines
for (individual in transformedList) {
result += individual
}
}
繰り返しになりますが、コレクションの初期化、反復、および平坦化は、 flatMap()の非表示の実装詳細の一部です。 私たちがしなければならないのは、変換関数を提供することだけです。
4. 結論
この記事では、Kotlinの map()と flatMap()の違いを学びました。 要約すると、 map()は通常1対1のマッピングに役立ちますが、 flatMap()は1対多のマッピングを平坦化するのに役立ちます。
いつものように、すべての例はGitHubでから入手できます。