関数型インターフェースの色々

色んな関数型インターフェース

これまで、StreamAPIから派生して、ラムダ式や関数型インターフェースについて書いてきました。
そこではFunctionとConsumerを使っていましたが、他にもいろいろあるので使ってみます。

Runnable

public interface Runnable
void run()
オブジェクトが実装するインタフェースRunnableを使ってスレッドを作成し、そのスレッドを開始すると、独立して実行されるスレッド内で、オブジェクトのrunメソッドが呼び出されます。

引数も戻り値も持たず、ただ実行するだけ。

public class Studay {
    public static void main(String[] args) {
        Runnable Hello  = () -> System.out.println("Hello");
        Hello.run();//Hello
    }
}

引数や戻り値がないから、mapやforEachには使えなさそう。

Consumer

@FunctionalInterface
public interface Consumer
単一の入力引数を受け取って結果を返さないオペレーションを表します。Consumerは他のほとんどの関数型インタフェースと異なり、副作用を介して動作することを期待されます。
これは、accept(Object)を関数メソッドに持つ関数型インタフェースです。

引数を受け取って、戻り値は返さない。

public class Studay {
    public static void main(String[] args) {
        Consumer<String> Hello  = System.out::println;
        Hello.accept("Hello");
    }
}

引数があるので、メソッド参照でSystem.out::printlnができますね。
forEachの引数にも使えます。

Function

@FunctionalInterface
public interface Function<T,R>
1つの引数を受け取って結果を生成する関数を表します。
これは、apply(Object)を関数メソッドに持つ関数型インタフェースです。

1個の引数を受け取って、結果を返す関数型インターフェース。

public class Studay {
    public static void main(String[] args) {
        Function<String,Integer> Hello  = String::length;
        System.out.println(Hello.apply("Hello"));//5
    }
}

mapにも使えます。
変数名.lengthは、クラス名:lengthに書き換えられるんですね。

BiConsumer

@FunctionalInterface
public interface BiConsumer<T,U>
2つの入力引数を受け取って結果を返さないオペレーションを表します。これは、Consumerを、引数を2個取るように特殊化したものです。BiConsumerは他のほとんどの関数型インタフェースと異なり、副作用を介して動作することを期待されます。
これは、accept(Object, Object)を関数メソッドに持つ関数型インタフェースです。

引数を2つ受け取って、結果を返さない関数型インターフェース。

public class Studay {
    public static void main(String[] args) {
        BiConsumer<String,Integer> Hello  = Studay::helloCount;
        Hello.accept("Hello",1);//Hello1
    }
    public static void helloCount(String str , Integer num){
        System.out.println(str + num.toString());
    }
}

何に使えるのかなーって思って調べると、HashTableのforEachで使えました。

public class Studay {
    public static void main(String[] args) {
        HashMap<String,Integer> hashMap = new HashMap<String,Integer>();
        BiConsumer<String,Integer> helloCount = (str,num) -> System.out.println(str + num.toString());
        hashMap.put("one",1);
        hashMap.put("two",2);
        hashMap.forEach(Studay::helloCountFunc);
        hashMap.forEach(helloCount);
    }
    public static void helloCountFunc(String str , Integer num){
        System.out.println(str + num.toString());
    }
}

難しくなってきた…。

Predicate

@FunctionalInterface
public interface Predicate
1つの引数の述語(boolean値関数)を表します。
これは、test(Object)を関数メソッドに持つ関数型インタフェースです。

引数を1つ受け取ってBoolean型を返す感じかな?

public class Studay {
    public static void main(String[] args) {
        Predicate<String> overten = (str) -> str.length() > 10;
        System.out.println(overten.test("Hello"));
        System.out.println(overten.test("Helloooooooooo"));
    }
}

これも何に使えるかな?と調べてみると、StreamAPIのfilterで使えました。

public class Studay {
    public static void main(String[] args) {
        Predicate<String> overten = (str) -> str.length() > 10;
        List<String> hello = Arrays.asList("Hello","Helloooooooooo");
        hello.stream().filter(overten).forEach(System.out::println);//Helloooooooooo
    }
}

BiPredicate

@FunctionalInterface
public interface BiPredicate<T,U>
2つの引数の述語(boolean値関数)を表します。これは、Predicateを、引数を2個取るように特殊化したものです。

Predicateの引数が2つあるバージョン。

public class Studay {
    public static void main(String[] args) {
        Integer chk = 5;
        BiPredicate<Integer,Integer> test = (num1,num2) -> num1 >= num2;
        IntStream.rangeClosed(1,10).filter(num->test.test(chk,num)).forEach(System.out::println);//1,2,3,4,5
    }
}

色々あるなぁ。
でも、何個も書いていくうちにラムダ式やメソッド参照についても慣れてきました。
現場で出たときも混乱せず読んでいきたいです。