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?

関数型インターフェースとラムダ式

Posted at

関数型インターフェースとは

関数型インターフェースは抽象メソッドが1つだけ定義されてるインターフェース

その抽象メソッドをラムダ式で楽に実装しようというもの
つまり、関数型インターフェースとラムダ式は基本セットで使う(ずっ友)

抽象メソッドが1つだけ定義されていればよい(2つ以上はダメ)ので以下のメソッドはあってもなくてもいい

  • 具象メソッド
  • defaultメソッド
  • privateメソッド
  • staticメソッド

ローカルクラス

メソッドやコンストラクタや初期化子の中に定義されたクラス

アクセスできるのは定義されたメソッドやコンストラクタだけなのでアクセス修飾子をつける必要がない
メソッドやコンストラクタ内で値が変わる変数にはアクセスできない(値が再代入されない、実質的finalな変数にしかアクセスできない

以下の例でいうと

  1. メソッド呼び出し時にnumが作られる
  2. あるタイミングでローカルクラスのインスタンス生成
    このときにnumの値をコピっといて持っておく

このような処理を辿るため、あとで「値がちがう!」と整合性がなくなるのを防ぐため

void method() {
    int num = 10;
    num++;  // ← ここで実質的finalでなくなる

    class Local {
        void print() {
            System.out.println(num);  // エラー!
        }
    }
}

アクセス修飾子をつけるとエラー

SE16からはレコードも定義できるようになったぽい

匿名クラス

Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("匿名クラスから実行中!");
    }
};

r.run(); // 出力: 匿名クラスから実行中!

クラス宣言と同時にインスタンス化をする

newの後に書いたクラスを継承した無名のサブクラスを即席で作成する
名前がないので独自のコンストラクタ定義はできない

ラムダ式

BiConsumer<Integer, Integer> printer = (a, b) -> System.out.println(a + b);
printer.accept(2, 4); // 出力: 6

関数型インターフェースの抽象メソッドを実装するときに使う

構文は (引数) -> 処理 の形。
引数がない場合は ()、戻り値を返す処理を右側に書く。
1文のみなら {} を省略でき、JavaScriptの無名関数に似ている。

関数型インターフェースの種類

①java.util.function.Supplierインターフェース

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

Supplierは提供者。
抽象メソッドであるgetメソッドが定義されている

実装方法

Supplier<List<String>> supplier = () -> new ArrayList();

提供者なので引数を渡さずに値を返してくれるいいやつ
戻り値はSupplierの右に書いたジェネリクスと同じ型が返る必要がある
上記でいうとList<String>の型が返る

呼び出し方法

List<String> list = supplier.get();

②java.util.function.Consumerインターフェース

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}

Consumerは消費者
抽象メソッドであるacceptメソッドが定義されている

実装方法

Consumer<String> printer = str -> System.out.println("こんにちは " + str);

消費者なので受け取った引数を使っちゃって処理をする
引数はConsumerの右に書いたジェネリクスと同じ型を渡す必要がある

呼び出し方法

printer.accept("Nicole");  // 出力:こんにちは Nicole

引数を二つ受け取りたい場合

「java.util.function.BiConsumer」を使おう

実装方法、呼び出し方法はConsumerとほぼ同じ
違うのはジェネリクスの数だけ

BiConsumer<Integer, Integer> addAndPrint = (a, b) -> System.out.println(a + b);
addAndPrint.accept(3, 5); // 出力: 8

③java.util.function.Predicateインターフェース

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}

Predicateは断定する
抽象メソッドはtestメソッドが定義されている

実装方法

Predicate<String> isEmpty = s -> s.isEmpty();

断定する人なので受け取った引数を使って判断をしてくれる裁判官
戻り値はboolean型
引数はPredicateの右に書いたジェネリクスと同じ型を渡す必要がある

呼び出し方法

System.out.println(isEmpty.test("")); // true

引数を二つ受け取りたい場合

「java.util.function.BiPredicate」を使おう

実装方法、呼び出し方法はPredicateとほぼ同じ
違うのはジェネリクスの数だけ

BiPredicate<String, Integer> isLongerThan = (str, len) -> str.length() > len;
System.out.println(isLongerThan.test("hello", 3)); // → true

④java.util.function.Functionインターフェース

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

抽象メソッドはapplyメソッドが定義されている

実装方法

Function<String, Integer> lengthFunction = s -> s.length();

ジェネリクスで指定された型に従って受け取った引数を使って値を返してくれる商人
上記でいうとString型のお金を渡してInteger型の商品をもらう

呼び出し方法

System.out.println(lengthFunction.apply("hello")); // 5

引数を二つ受け取りたい場合

「java.util.function.BiFunction」を使おう

実装方法、呼び出し方法はFunctionとほぼ同じ
違うのはジェネリクスの数だけ

BiFunction<String, Integer, String> repeat = (str, times) -> str.repeat(times);
System.out.println(repeat.apply("Hi", 3)); // HiHiHi

⑤5java.util.function.UnaryOperatorインターフェース

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
    // Function<T, T> を継承している
}


Functionを継承しているため抽象メソッドはapplyメソッドが定義されている

実装方法

UnaryOperator<String> toUpper = s -> s.toUpperCase();

ジェネリクスで指定された型に従って受け取った引数を使って値を返してくれる両替機
上記でいうとString型のお金を渡してString型のお金を返す

呼び出し方法

System.out.println(toUpper.apply("hello")); // HELLO

引数を二つ受け取りたい場合

「java.util.function.BinaryOperator」を使おう

実装方法、呼び出し方法はUnaryOperatorとほぼ同じ
違うのはジェネリクスの数だけ

BinaryOperator<Integer> sum = (a, b) -> a + b;
System.out.println(sum.apply(3, 5)); // 8
0
0
1

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?