🐈

【Java】関数型インターフェース

に公開

https://zenn.dev/codek2/articles/069afe4a5bf986

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

1つの抽象メソッドを持つインターフェース

例)Consumer<T> ※一部省略しています

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

メリット

  • コードが簡潔になる
  • わざわざクラスを作成する必要がない

従来のインターフェースを使用した例

package functionInterfaceTest;

public interface Printer {
	void print(String message);
}
package functionInterfaceTest;

public class ConsolePrinter implements Printer {
	@Override
	public void print(String message) {
		System.out.println(message);
	}
}
package functionInterfaceTest;

public class Main {
	public static void main(String[] args) {
		Printer printer = new ConsolePrinter();
		printer.print("こんにちは!");
	}
}

関数型インターフェースを使うと?

ConsolePrinterクラスを作成せずにインターフェースをその場で使用することが出来る
※上記のPrinterインターフェースが記述されていることが必要

package functionInterfaceTest;

import java.util.function.Consumer;

public class ConsumerMain {
	public static void main(String[] args) {
		Consumer<String> printer = message -> System.out.println(message);
		//こんにちは!
		printer.accept("こんにちは!");
	}
}

よく使われる関数型インターフェース

インターフェース 分類
Consumer<T> 引数を1つ受け取り、戻り値を返さない
Supplier<T> 引数を受け取らず、戻り値を返す
Function<T, R> 引数を受け取り、戻り値を返す
Predicate<T> 引数を受け取り、true/false を返す
Runnable 引数を受け取らず、戻り値を返さない

使用例

Supplier<T>

何かを提供(供給)するためのインターフェース
Tの部分には「何を提供するのか」を記述(今回はLocalTime)

package functionInterfaceTest;

import java.time.LocalTime;
import java.util.function.Supplier;

public class SupplierMain {
	public static void main(String[] args) throws InterruptedException {
		//現在時刻を返す関数をtimeSupplier に保存
		Supplier<LocalTime> timeSupplier = () -> LocalTime.now();
		//1回目: 16:56:32.024806400
		System.out.println("1回目: " + timeSupplier.get());
		// 2秒待つ
		Thread.sleep(2000);
		// 新しい時刻を表示(2回目: 16:56:34.036926600)
		System.out.println("2回目: " + timeSupplier.get());
	}
}

<出力例>

Function<T, R>

T(入力)をR(出力)に変換する関数

package functionInterfaceTest;

import java.util.function.Function;

//文字列を整数に変換
public class FunctionTest {
	public static void main(String[] args) {
		Function<String, Integer> toInt = Integer::parseInt;
		System.out.println(toInt.apply("123")); //123
	}
}

Predicate<T>

条件を判定するときに使用

package functionInterfaceTest;

import java.util.function.Predicate;
//数字が偶数かどうかを判定
public class PredicateMain {
	public static void main(String[] args) {
		Predicate<Integer> isEven = n -> n % 2 == 0;

		System.out.println(isEven.test(10)); // true
		System.out.println(isEven.test(7)); // false
	}
}

Runnable

何らかの処理を実行するためのインターフェース
スレッドの実行に使われることが多い
何かを実行したいけど、引数も戻り値もいらないというときに使用

Runnable の特徴:run()メソッドしかない

package functionInterfaceTest;

public class RunnableTest {
	public static void main(String[] args) {
		//Runnable task:Runnable 型の変数taskを作成
		//():run()メソッドの定義(引数なし)
		//System.out.println("タスク実行中..."); :run()の処理(画面に表示)
		Runnable task = () -> System.out.println("タスク実行中...");
		task.run();
	}
}

<出力例>

https://zenn.dev/codek2/articles/7fbfa22ba62e69

Udemyで講座を公開中!
https://zenn.dev/codek2/articles/e9e44f3e0023fb

X(旧Twitter)
https://twitter.com/kunchan2_

Zenn 本
https://zenn.dev/codek2?tab=books

Youtube
https://www.youtube.com/@codek2_studio

Discussion