Javaのラムダ式とは?メリット・デメリットから使い方まで解説!
thumb_javalambdaexpression_01
Javaのラムダ式とは?メリット・デメリットから使い方まで解説!
アンドエンジニア編集部
2023.10.23
この記事でわかること
Javaのラムダ式とは、Java 8(JDK1.8)から追加された機能で簡素化する表記法を指します
ラムダ式は、合わせてリリースされたStream APIで利用すると一層効果的です
使いどころによって、読みやすいコードが開発可能で開発・保守の生産性向上が期待できます

Javaのラムダ式とは

img_javalambdaexpression_01

Javaのラムダ式とは、Java 8(JDK1.8)から追加された表記法の1つを表します。関数型プログラミングのスタイルをサポートしており、匿名クラスに対してラムダ式で記述することができます。メソッドを変数と同様に扱うことでコードの記述を減らし、シンプルで柔軟なプログラムを作成することができます。

【参考】:Oracle Japan / オラクルの技術リソース 【参考】:Oracle Japan / オラクルの技術リソース Java SE ドキュメント 【参考】:Oracle Java ® Platform, Standard Edition & Java Development Kit バージョン18 API仕様 【参考】:Oracle Java 8: Lambdas, Part 1 【参考】:Oracle Java 8: Lambdas, Part 2

そもそもラムダ式とは

ラムダ式は、無名関数や匿名関数と呼ばれる名前付けされずに定義された関数(名前のない関数)を記述するための表記法を表します。通常は関数の定義を行う場合に名前を設定しますが、無名関数では名前を付ける必要がありません。

この表記法は、多くのプログラミング言語で取り入れられており、JavaのほかにC++やC#、JavaScript・PHP・Pythonなどで対応しています。

C#とは?できることやメリット・デメリットについて解説!
Pythonの勉強方法・手順とは?具体的なロードマップを解説!

ラムダ式のメリット

ラムダ式の一般的なメリットは、関数の名前を考える必要がなく、余計な手間がかからないことが挙げられます。1度しか使わない関数であれば、ラムダ式がより便利です。

Javaの場合でも、クラスの定義とインスタンスの生成を合わせて行うことができますので、コードの記述がシンプルになるメリットがあり、簡潔でわかりやすいコードを書くことができます。ラムダ式を使用することで、無名の関数を作成でき、関数を引数として渡したり、戻り値として返したりすることができます。

このようにコードをより効率的に記述することができるほか、コードの書き方が変わるため、アプリケーションのパフォーマンスも向上する場合もあります。

ラムダ式のデメリット

ラムダ式のデメリットですが、一般的にはプログラムコードの名前参照ができないことが挙げられます。何度も使用したり再帰的に使用したりする場合は、通常の記述方法の方が分かりやすいコードが作成できます。

Javaの場合においても、いくつか制限があります。

ラムダ式を使用するには、「関数型インターフェース」以外には使用できないという制限があります。これまでの匿名クラスのように扱う変数はfinalもしくは実質的にfinalのため、参照のみとしてアクセスする必要があります。ここでいうfinalとは変更不可の状態を指します。

ラムダ式ではデバッグが難しい場合があり、その実行が失敗した場合、スタックトレースから呼び出し元を特定することが困難になります。複雑なラムダ式を記述すると、コードが読みにくくなることがあります。

ラムダ式が登場した際には、このような制限から可読性が落ちるという理由で、開発規則で禁止となる事例も見られました。これはデメリットというよりは、メリットが理解できずに実際の利用が進まなかったという方が正しいです。

とは言ってもラムダ式は簡潔である反面、処理が複雑になるとコードの保守性が低下することがありますので、適切な場面でのみ使用することが望ましいです。

Javaのラムダ式を使ってみる

img_javalambdaexpression_02

Javaのラムダ式の使いどころですが、関数を引き渡す「関数型インターフェース」を簡単に実装したい場合に用います。Java 8でサポートされた、要素データの大量処理に利用するStream APIもラムダ式でサポートされます。使い方は、以降で解説していきます。

ラムダ式の書式

ラムダ式の書式は単純です。与える引数に処理を行い結果を戻すもので、次のように表記します。

(引数1, 引数2, …) -> {return 処理内容};

 

引数が1つのみの場合は、丸括弧(”( )”)を省略できます。引数がない場合は省略できません。同様に処理内容が1行で表すことができる場合は、波括弧(”{ }”)やreturnを省略することができます。

引数 -> 処理内容;

 

プログラムコードに”->”が現れたら、ラムダ式で記述していると理解していれば問題ありません。

ラムダ式を関数型インターフェースで使用する

「関数型インターフェース」とは、抽象メソッドが1つだけの抽象クラスを指します。ラムダ式は、関数型インターフェースで使用することができます。

次の例は、1〜10までの数字の合計値を計算するJavaプログラムです。

import java.util.*;

public class Main {     public static void main(String[] args) throws Exception {         // 開始と終了を設定する         int start = 1;         int end = 10;

        int sum = 0;         for (int i = start; i <= end; i++) {             sum += i; // 合計値を計算する         }

        System.out.println(start + " から " + end + " までの合計は " + sum);     } }

 

実行結果は以下の通りで、よくご存じの結果(55)が表示されます。

1 から 10 までの合計は 55

 

ここでは、ラムダ式を学ぶためにStream APIのreduceという合算値を求める関数(累積関数)にラムダ式を代入してみます。コメントの”// 合計値の計算”の部分を差し換えてみました。

import java.util.*; import java.util.stream.IntStream;

public class Main {     public static void main(String[] args) throws Exception {         // 開始と終了を設定する         int start = 1;         int end = 10;

        int sum = IntStream.rangeClosed(start, end)                           .reduce(0, (a, b) -> a + b); // 合計値を計算する

        System.out.println(start + " から " + end + " までの合計は " + sum);     } }

 

実行結果は同じですので割愛しますが、このreduceで示した” (a, b) -> a + b”がラムダ式です。

【参考】:パッケージjava.util.function - 関数型インタフェース

ラムダ式をStream APIで使用する

「Stream API」とは、配列やListで表される要素データを簡潔に記述するためのAPIです。記法は次の通りで、処理を数珠つなぎに行っていきます。

collection.stream().中間操作().中間操作().終端操作();

 

公式ドキュメントに掲載されているサンプルコードに見られるように、ラムダ式を次のようにパラメータで渡すことができます。

    int sum = widgets.stream()
                   .filter(w -> w.getColor() == RED)
                   .mapToInt(w -> w.getWeight())
                   .sum();```

 

このように、filterやmapToIntなどの中間操作のAPIでラムダ式を用いると、データの流れ(ストリーム、Stream)がスムーズに処理できるメリットがあります。Stream APIは関数型インターフェースですので、ラムダ式を使用するにはうってつけです。

Stream APIの使用方法を、実際に見ていきましょう。次の例は、データの入っているリストに1〜5の値が格納されています。その中で奇数のみを抽出して合計値を表示します。

import java.util.*; import java.util.ArrayList; import java.util.List;

public class Main {     public static void main(String[] args) {         // リストデータを作成         List data = new ArrayList<>();         data.add(1);         data.add(2);         data.add(3);         data.add(4);         data.add(5);

        // Stream APIを用いて奇数のみを抽出し、合算集計する         int sum = data.stream()                       .filter(n -> n % 2 == 1) // 奇数のみを抽出する                       .mapToInt(Integer::intValue) // 値をint型に変換する                       .sum(); // 合計値を計算する

        data.forEach(s -> System.out.println(s)); // Listの表示         System.out.println("奇数の合計は " + sum); // 奇数の合計の表示     } }

 

実行結果は、次の通りです。

1
2
3
4
5
奇数の合計は 9

 

中間操作のfilterで用いた”n -> n % 2” がラムダ式です。ラムダ式を使用しない場合は、ロジックを別に用意する必要があります。後半にあるListの表示部分も、forEachでラムダ式の”s -> System.out.println(s)” を使用することで簡素化することができます。

【参考】:Stream (Java SE 18 & JDK 18)

Web APIとは?仕組みや使い方、メリットをわかりやすく解説!

Javaのラムダ式は利用価値が高い

img_javalambdaexpression_03

Javaのラムダ式は、コーディングの作法に慣れてしまえばそんなに難しくありません。むしろ簡素なコード作成に役立ち、メンテナンスも楽になります。使いどころを間違えずに、要所をおさえた利用が望まれます。

これにより、実際のプロジェクトなどの大規模開発においても高い開発と保守の生産性が期待でき、利用価値が高まります。

OpenJDK 18が正式リリース!Java 18の新機能を解説
気になる人のXをフォローしよう!
アンドエンジニア公式LINEでは
新着記事やエンジニアに役立つ情報をお届け!
日々のキャッチアップをお手伝いします!
マイナビITエージェント

編集部オススメコンテンツ

Sponsored
【年収±診断】6つの質問に答えて、真の市場価値をチェック!
マイナビITエージェント
Sponsored

アンドエンジニアへの取材依頼、情報提供などはこちらから

お問い合わせ・情報提供
はじめて転職される方へ
SE・システムエンジニア(IT/通信/インターネット) 求人一覧

編集部おすすめコンテンツ

Sponsored
【年収±診断】6つの質問に答えて、真の市場価値をチェック!
マイナビITエージェント
Sponsored

アンドエンジニアへの取材依頼、情報提供などはこちらから

Powered by マイナビ AGENT