(Java8)関数型インターフェースの使用方法

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

  • Function

  • Predicate

  • Consumer

  • Supplier


Function

Functionインターフェースは、引数を受け取って処理を行い返却する。 例はCSVを受け取って分割しリストに変換している。

   public static void main(String[] args) {
        
        Function<String, List<String>> f = (line) -> {
            String[] array = line.split(",");
            List<String> returnList = Arrays.asList(array);
            return returnList;
        };

        List<String> list = f.apply("1,2,3,4,5");
        list.forEach(System.out::println);
        
    }

結果

1
2
3
4
5

Predicate

Predicateは、引数を受け取って判断し、booleanを返す。 例は文字列が3文字以上かを判断している。

   public static void main(String[] args) {

        Predicate<String> f = s -> s.length() > 3;
        
        Arrays.asList("a", "bb", "ccc", "ddd", "eeee", "fffff").stream()
            .filter(s -> f.test(s))
            .forEach(System.out::println);
    }

結果

eeee
fffff

Consumer

Consumerインターフェースは、引数を受け取って消費する。 例は引数を標準出力に表示しているだけ。

   public static void main(String[] args) {

        Consumer<String> f = s -> System.out.println(s);
        List<String> list = Arrays.asList("a", "b", "c");
        list.stream()
            .forEach(s -> f.accept(s));

    }

結果

a
b
c

Supplier

Supplierインターフェースはある決まったものを返す。

   public static void main(String[] args) {

        Supplier<String> f = () -> "Supplier";

        IntStream.rangeClosed(1, 3)
            .forEach(i -> System.out.println(f.get()));

    }

結果

Supplier
Supplier
Supplier

ここまでのサンプルじゃあ恩恵もないし、わざわざ使わなくてもと思うし、関数型インターフェース使わなくてもストリームの中でラムダでいいじゃんというのもある意見だと思うけど、ある程度の量のラムダだと可読性がひどく悪い。
ので、ここで関数型インターフェースを使う。(と、思うんだ。)

ここでは、一番使うであろうFunctionインターフェースを例にしてみる。
Functionインターフェース「f」はCSVのリストをFlatMapして返す。(FlatMapについては前日のエントリを参照)

    public static void main(String[] args) {

        Function<String, List<String>> f = s -> {
            String[] array = s.split(",");
            List<String> list = Arrays.asList(array);
            return list;
        };
        
        List<String> list = new ArrayList<>();
        list.add("1,2,3");
        list.add("4,5");
        list.add("6,7,8,9");
        
        list.stream()
            .flatMap(line -> f.apply(line).stream()))
            .collect(Collectors.toList())
            .forEach(System.out::println);;
        
    }

結果

1
2
3
4
5
6
7
8
9

関数型インターフェースを使った関数を使ったことによってStream処理のところがとても読みやすくないかい?