Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
Predicate / Function / Consumer / Supplier
Java 8で追加された主要な関数型インターフェースです。ラムダ式やメソッド参照と組み合わせて使います。それぞれ「判定・変換・消費・生成」という役割を持ちます。
構文
// Predicate<T>: T を受け取り boolean を返します。
Predicate<T> pred = (T t) -> /* boolean式 */;
boolean result = pred.test(t);
// Function<T, R>: T を受け取り R を返します。
Function<T, R> func = (T t) -> /* R型の値 */;
R result = func.apply(t);
// Consumer<T>: T を受け取り何も返しません。
Consumer<T> cons = (T t) -> { /* 処理 */ };
cons.accept(t);
// Supplier<T>: 引数なしで T を返します。
Supplier<T> supp = () -> /* T型の値 */;
T value = supp.get();
// BiFunction<T, U, R>: 2引数を受け取り R を返します。
BiFunction<T, U, R> bif = (T t, U u) -> /* R型の値 */;
// UnaryOperator<T>: T を受け取り同じ型 T を返します。
UnaryOperator<T> op = (T t) -> /* T型の値 */;
主な関数型インターフェース一覧
| インターフェース | 抽象メソッド | 概要 |
|---|---|---|
| Predicate<T> | test(T t) → boolean | 条件判定に使います。ストリームの filter() などに渡します。 |
| Function<T, R> | apply(T t) → R | 値を変換します。ストリームの map() などに渡します。 |
| Consumer<T> | accept(T t) → void | 値を受け取って処理し、何も返しません。forEach() などに渡します。 |
| Supplier<T> | get() → T | 引数なしで値を生成・返します。遅延評価に使います。 |
| BiFunction<T, U, R> | apply(T t, U u) → R | 2つの引数を受け取り値を返します。 |
| BiConsumer<T, U> | accept(T t, U u) → void | 2引数を受け取り処理します。Map.forEach() などに渡します。 |
| UnaryOperator<T> | apply(T t) → T | 同じ型の変換を行います。Function<T,T> の特化型です。 |
| BinaryOperator<T> | apply(T t, T u) → T | 同じ型の2引数を受け取り同じ型を返します。reduce() などに渡します。 |
サンプルコード
import java.util.*;
import java.util.function.*;
// Predicate: 偶数かどうかを判定します。
Predicate<Integer> isEven = n -> n % 2 == 0;
System.out.println(isEven.test(4)); // 『true』と出力されます。
System.out.println(isEven.test(7)); // 『false』と出力されます。
// Predicateの合成: and() / or() / negate() で組み合わせます。
Predicate<Integer> isPositive = n -> n > 0;
Predicate<Integer> isEvenAndPositive = isEven.and(isPositive);
System.out.println(isEvenAndPositive.test(4)); // 『true』と出力されます。
System.out.println(isEvenAndPositive.test(-2)); // 『false』と出力されます。
// Function: 文字列を大文字に変換します。
Function<String, String> toUpper = String::toUpperCase;
System.out.println(toUpper.apply("hello")); // 『HELLO』と出力されます。
// Functionの合成: andThen() で連結します。
Function<String, Integer> toLength = String::length;
Function<String, Integer> upperLength = toUpper.andThen(toLength);
System.out.println(upperLength.apply("hello")); // 『5』と出力されます。
// Consumer: リストの各要素を出力します。
Consumer<String> printer = s -> System.out.println("> " + s);
List.of("A", "B", "C").forEach(printer);
// Supplier: 遅延評価でデフォルト値を生成します。
Supplier<List<String>> listFactory = ArrayList::new;
List<String> newList = listFactory.get();
newList.add("item");
System.out.println(newList); // 『[item]』と出力されます。
概要
これらのインターフェースは java.util.function パッケージに含まれており、ラムダ式・メソッド参照の型として使われます。ストリームAPIや Optional でも広く使われているため、使い方を覚えておくと非常に便利です。
Predicate は and() / or() / negate()、Function は andThen() / compose() でメソッドを合成できます。プリミティブ型専用の IntPredicate・IntFunction<R>・IntConsumer・IntSupplier などを使うとオートボクシングのコストを避けられます。
ラムダ式の書き方については『ラムダ式 / (x) -> x * 2』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。