覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。twitter: @yyoshikaw

Kotlin - 簡単なラムダ式を試す

ラムダ式(lambda exoression)または単にラムダ(lambda)とは、本質的には他の関数に渡すことが可能なコードの断片です。
ラムダを利用することで、共通のコード構造を抜き出してライブラリ関数へ渡すこことが可能です。
Kotlin の標準ライブラリはラムダを多用していて、ラムダの最も一般的な利用用途はコレクションの操作です。


以下でKotlinのコードで簡単なコレクションの操作を行ってみます。

data class Product(val name: String, val price: Int)

上記クラスのインスタンスを複数詰め込んだリスト内から最も高い価格(price)のものを見つけるという処理を行います。

サンプルコードで対象のリストは以下のものとします

val products = listOf(Product("A", 10), Product("B", 1), Product("C", 1000))


命令的に、この処理を素直に記述すると以下のようになります。

fun findHighestProduct(products: List<Product>): Product? {
    var maxPrice = 0
    var highestProduct: Product? = null

    for (product in products) {
        if (product.price > maxPrice) {
            maxPrice = product.price
            highestProduct = product
        }
    }

    return highestProduct
}

実行コードは以下のよになります

val products = listOf(Product("A", 10), Product("B", 1), Product("C", 1000))
val highestProduct1 = findHighestProduct(products)  // -> Product(name=C, price=1000)


ラムダ式

Kotlin ではコレクションに対して maxBy 関数を利用することが可能です。
引数には、最大要素を見つけるために比較する値を指定する関数を指定する必要があります。

以下のように記述できます。波括弧内のコードはラムダ式であり、関数の引数として渡します。

val highestProduct = products.maxBy({p: Product -> p.price})

この記述はもっと簡単な記述にできます。
Kotlin では構文規約でラムダ式が関数呼び出しの最終引数であれば括弧の外に移動することが可能です。
この規約を利用すると以下のように記述できます

val highestProduct = products.maxBy() {p: Product -> p.price}

ラムダが関数の唯一の引数であれば、関数呼び出しから空の括弧を取り除いて記述できます。そうすると以下のようになります。

val highestProduct = products.maxBy {p: Product -> p.price}

上記3つの構文は同じことを意味しています。


ラムダの引数の型を推論できる場合は、明示的な指定は不要です。maxBy関数では、その引数の型は常にコレクションの要素の型と同じです。
そのため以下のように型を省いて記述することもできます。

val highestProduct = products.maxBy {p -> p.price}


ちなみにさらなる短絡構文で it を利用して以下のように記述することもできます

val highestProduct = products.maxBy { it.price }

it を用いてコレクション要素を引数として受け取っています。


今回比較する値は price であり、この値は price プロパティに保持されています。
ラムダが単に関数やプロパティを呼び出すだけの場合は、ラムダはメンバ参照を用いて記述することも可能です。

val highestProduct = products.maxBy(Product::price)


まとめ

今回は、Kotlinにおけるコレクションの簡単な操作をラムダ式を使って試してみました。