0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Java SE 11 Silver 学習 ラムダ式

Posted at

はじめに

本ドキュメントで解説する内容

  • 関数型インタフェース
  • ラムダ式
  • メソッド参照
  • コンストラクタ参照
  • Java標準ライブラリにおける関数型インタフェース
    - Runnable/Callable
    - Comparator#compare
    - Supplier#get
    - Consumer#accept
    - Predicate#test
    - Function#apply
    - Operator#apply

関数型インタフェース

  • 抽象メソッドが1つのみ定義されているインターフェース。
  • ラムダ式、メソッド参照、またはコンストラクタ参照を使って関数型インタフェースのインスタンスを作成できる。

TIPS

  • 関数型インタフェースにはstaticメソッドやデフォルトメソッドが含まれていても構わない(関数型インターフェースとしては無視される)
  • FunctionalInterfaceアノテーションをインタフェース定義に追加すると、インタフェースが関数型インタフェースの要件を満たすかどうかを静的にチェックできる。

関数型インタフェースの例

package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

   static <T> Function<T, T> identity() {
        return t -> t;
    }
}

ラムダ式

  • 関数型インターフェースのメソッドを実装(オーバーライド)する記法。
  • インターフェース変数にラムダ式を代入することで、関数型インタフェースのインスタンスを簡易に記述できる。
    引数部 -> 本体部
    

TIPS

  • 以下の2つの式により生成されるインスタンスは同一となる。
無名クラス
  Function<Integer, String> f = new Function<>() {
    @Override
    public String apply(Integer i) {
        return String.valueOf(i);
    }
  };
ラムダ式
  Function<Integer, String>  = i -> String.valueOf(i);

引数部

  • 引数部で定義された変数は、本体部のみで利用可能となる。
  • ローカル変数と同一名称の変数を引数名に定義することはできない。
引数の数 記法 記載例
なし () () ->
1つ (型 変数名) (String name) ->
^ (変数名) (name) ->
^ 変数名 name ->
2つ以上 (型1 変数名1, 型2 変数名2) (String name, int i) ->
^ (変数名1, 変数名2) (name, i) ->

本体部

  • 本体部の処理において、以下の変数にアクセスできる。
    • クラスのフィールド(インスタンス/クラスフィールド)
    • ラムダ式の定義以前に宣言済のローカル変数のうち、finalまたは実質的finalのもの
戻り値 処理数 記法 記載例
void 1 処理を定義 -> System.out.println("A");
^ 1以上 各処理を{}で囲む -> { a.hoge(); b.fuga(); }
あり 1 値を返却する処理のみ定義 -> String.valueOf(10);
^ 1以上 各処理を{}で囲み、returnで返却 -> { a.hoge(); return a; }

メソッド参照

  • 関数型インターフェースの変数にメソッドそのものを代入すること。
  • 記法
    • インスタンスメソッドの場合: 変数名::メソッド名
    • staticメソッドの場合: クラス名::メソッド名
    • 自クラスのインスタンスメソッドの場合: this::メソッド名

TIPS

  • 以下の2つの式で実行される内容は同一となる。
    ラムダ式
      List.of(1,2,3).forEach(n -> System.out.print(n)); //123
    
    メソッド参照
      List.of(1,2,3).forEach(System.out::print); //123
    

コンストラクタ参照

  • 関数型インターフェースの変数にコンストラクタを代入すること。
  • 記法: クラス名::new

TIPS

  • 以下の2つの式で実行される内容は同一となる。
    ラムダ式
    List<Long> now = Arrays.asList(1680143332000L);
    now.stream().map(l -> new Date(l)).forEach(System.out::println); //Thu Mar 30 11:28:52 JST 2023
    
    コンストラクタ参照
    List<Long> now = Arrays.asList(1680143332000L);
    now.stream().map(Date::new).forEach(System.out::println);; //Thu Mar 30 11:28:52 JST 2023
    

標準の関数型インタフェース

  • Java標準ライブラリにおいて関数型インタフェースが提供されている。
  • 代表的な関数型インタフェースを以下に示す。
package 関数型インタフェース 概要
java.lang Runnable#run 引数なしで処理を行い、結果を返さない(検査例外なし)
java.util.concurrent Callable#call 引数なしで処理を行い、結果を返さない(検査例外あり)
java.util Comparator#compare 2つのオブジェクトの大小比較を行う
java.util.function Supplier#get 引数なしで処理を行い、任意の結果を返す
java.util.function Consumer#accept 引数ありで処理を行い、結果を返さない
java.util.function Predicate#test 引数ありで処理を行い、真偽値で結果を返す(条件判定)
java.util.function Function#apply 引数ありで処理を行い、任意の結果を返す
java.util.function UnaryOperator#apply 引数ありで処理を行い、引数と同一の型を返す

Runnable/Callable

関数型インタフェース メソッド 引数の数 戻り値
Runnable void run() 0 メソッドはどのようなアクションを実行してもかまわない
Callable<V> V call() 0 結果を計算するか、計算できない場合は例外をスローする

Comparator#compare

関数型インタフェース メソッド 引数の数 戻り値
Comparator<T> int compare​(T o1, T o2) 2 o1がo2よりも小さい場合は負の整数、等しい場合はゼロ、大きい場合は正の整数を返す

Supplier#get

  • 引数なしで処理を行い、結果を返す。
関数型インタフェース メソッド 引数の数 戻り値
Supplier<T> T get() 0 総称型(T)
BooleanSupplier boolean getAsBoolean 0 boolean
IntSupplier int getAsInt() 0 int
LongSupplier long getAsLong() 0 long
DoubleSupplier double getAsDouble() 0 double

Consumer#accept

  • 引数ありで処理を行い、結果を返さない。
関数型インタフェース メソッド 引数の数 戻り値
Consumer<T> void accept(T t) 1 void
IntConsumer void accept(int value) 1 void
LongConsumer void accept(long value) 1 void
DoubleConsumer void accept(double value) 1 void
BiConsumer<T, U> void accept(T t, U u) 2 void
ObjIntConsumer<T> void accept(T t, int value) 2 void
ObjLongConsumer<T> void accept(T t, long value) 2 void
ObjDoubleConsumer<T> void accept(T t, double value) 2 void

Predicate#test

  • 引数ありで処理を行い、真偽値で結果を返す(条件判定)。
関数型インタフェース メソッド 引数の数 戻り値
Predicate<T> boolean test(T t) 1 boolean
Consumer<T> boolean test(T t) 1 boolean
IntPredicate boolean test(int value) 1 boolean
LongPredicate boolean test(long value) 1 boolean
DoublePredicate boolean test(double value) 1 boolean
BiPredicate<T, U> boolean test(T t, U u) 2 boolean

Function#apply

  • 引数ありで処理を行い、結果を返す。
関数型インタフェース メソッド 引数の数 戻り値
Function<T, R> R apply(T t) 1 総称型(R)
IntFunction<R> R apply(int value) 1 総称型(R)
LongFunction<R> R apply(long value) 1 総称型(R)
DoubleFunction<R> R apply(double value) 1 総称型(R)
BiFunction<T, U, R> R apply(T t, U u) 2 総称型(R)
ToIntFunction<T> int applyAsInt(T value) 1 int
LongToIntFunction int applyAsInt(long value) 1 int
DoubleToIntFunction int applyAsInt(double value) 1 int
ToIntBiFunction<T, U> int applyAsInt(T t, U u) 2 int
ToLongFunction<T> long applyAsLong(T value) 1 long
IntToLongFunction long applyAsLong(int value) 1 long
DoubleToLongFunction long applyAsLong(double value) 1 long
ToLongBiFunction<T, U> long applyAsLong(T t, U u) 2 long
ToDoubleFunction<T> double applyAsDouble(T value) 1 double
IntToDoubleFunction double applyAsDouble(int value) 1 double
LongToDoubleFunction double applyAsDouble(long value) 1 double
ToDoubleBiFunction<T, U> double applyAsDouble(T t, U u) 2 double

Operator#apply

  • 引数ありで処理を行い、引数と同一の型を返す。
関数型インタフェース メソッド 引数の数 戻り値
UnaryOperator<T> T apply(T t) 1 総称型(T)
IntUnaryOperator T applyAsInt(int operand) 1 int
LongUnaryOperator T applyAsLong(long operand) 1 long
DoubleUnaryOperator T applyAsDouble(double operand) 1 double
BinaryOperator<T> T apply(T t, T u) 2 総称型(T)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?