Java関数型インターフェース: メソッドと使用例

## この記事の対象者
Java 8以降を使用している開発者で、関数型インターフェースの基本的な使い方やメリットを理解したい方。

## 参照サイト
- [Oracle公式ドキュメント](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/FunctionalInterface.html)

## 開発環境
```
Java 8
Visual Studio Code
```

## 作成した関数型インターフェース一覧

| 関数名                | 具体的な用途 |
|-----------------------|----------------|
| BiConsumer<T,U>       | 2つの引数を受け取り、結果を返さない操作を表します。 |
| BiFunction<T,U,R>     | 2つの引数を受け取り、結果を返す関数を表します。 |
| BinaryOperator<T>     | 2つの同じ型のオペランドに対して操作を実行し、同じ型の結果を返す操作を表します。 |
| BiPredicate<T,U>      | 2つの引数を受け取り、boolean値の結果を返す述語（真偽値関数）を表します。 |
| Consumer<T>           | 1つの引数を受け取り、結果を返さない操作を表します。 |
| Function<T,R>         | 1つの引数を受け取り、結果を返す関数を表します。 |
| Predicate<T>          | 1つの引数を受け取り、boolean値の結果を返す述語を表します。 |
| Supplier<T>           | 引数を受け取らず、結果を供給する操作を表します。 |
| UnaryOperator<T>      | 1つのオペランドに対して操作を実行し、同じ型の結果を返す操作を表します。 |




## Function インターフェース
Function インターフェースは、Javaの関数型インターフェースの1つで、1つの引数を受け取り、結果を生成する関数を表します。このインターフェースはジェネリックを使用しており、`Function<T, R>` の形式で表されます。ここで T は入力の型を、R は戻り値の型を示します。

#### 主要なメソッド:


| メソッド名               | 具体的な内容 |
|------------------------|--------------------------------------------------|
| `apply(T t)`           | 指定された引数にこの関数を適用し、結果を返します。 |
| `andThen(Function after)` | この関数を入力に適用した後、その結果に関数 after を適用する合成関数を返します。 |
| `compose(Function before)` | 関数 before を入力に適用した後、その結果にこの関数を適用する合成関数を返します。 |
| `identity()`           | 常に入力引数をそのまま返す関数を返します。 |



```
// Function インターフェースの使用例
Function<Integer, String> intToString = num -> "Number: " + num;
System.out.println(intToString.apply(5));  // 出力: Number: 5

// andThen メソッドの使用例
Function<String, Integer> stringLength = str -> str.length();
Function<Integer, String> lengthToString = len -> "Length: " + len;
Function<String, String> combinedFunction = intToString.andThen(lengthToString);
System.out.println(combinedFunction.apply(12345));  // 出力: Length: 5

// compose メソッドの使用例
Function<String, String> composedFunction = intToString.compose(stringLength);
System.out.println(composedFunction.apply("12345"));  // 出力: Number: 5

// identity メソッドの使用例
Function<String, String> identityFunction = Function.identity();
System.out.println(identityFunction.apply("Hello"));  // 出力: Hello
```


上記のハンズオンでは、Function インターフェースの主要なメソッドの使用方法を示しています。ジェネリックを使用することで、さまざまな型の入力と出力を持つ関数を簡単に定義することができます。


## BiFunction インターフェース
BiFunction インターフェースは、Javaの関数型インターフェースの1つで、2つの引数を受け取り、結果を生成する関数を表します。このインターフェースはジェネリックを使用しており、`BiFunction<T, U, R>` の形式で表されます。ここで T と U は入力の型を、R は戻り値の型を示します。

#### 主要なメソッド:

| メソッド名               | 具体的な内容 |
|------------------------|--------------------------------------------------|
| `apply(T t, U u)`      | 指定された2つの引数にこの関数を適用し、結果を返します。 |
| `andThen(Function after)` | この関数を入力に適用した後、その結果に関数 after を適用する合成関数を返します。 |


```
// BiFunction インターフェースの使用例
BiFunction<Integer, Integer, String> sumToString = (a, b) -> "Sum: " + (a + b);
System.out.println(sumToString.apply(3, 4));  // 出力: Sum: 7

// andThen メソッドの使用例
Function<String, Integer> stringLength = str -> str.length();
BiFunction<Integer, Integer, String> sumAndLength = sumToString.andThen(stringLength);
System.out.println(sumAndLength.apply(3, 4));  // 出力: 6 (文字列"Sum: 7"の長さ)
```


## Consumer インターフェース
Consumer インターフェースは、単一の入力引数を受け取り、結果を返さないオペレーションを表します。このインターフェースはジェネリックを使用しており、`Consumer<T>` の形式で表されます。ここで T は入力の型を示します。

#### 主要なメソッド:

| メソッド名               | 具体的な内容 |
|------------------------|--------------------------------------------------|
| `accept(T t)`          | 指定された引数でこのオペレーションを実行します。 |
| `andThen(Consumer after)` | このオペレーションを実行した後、続けて after オペレーションを実行する合成Consumerを返します。 |


```
// Consumer インターフェースの使用例
Consumer<String> greet = name -> System.out.println("Hello, " + name + "!");
greet.accept("Alice");  // 出力: Hello, Alice!

// andThen メソッドの使用例
Consumer<String> shout = name -> System.out.println(name.toUpperCase() + "!");
greet.andThen(shout).accept("Alice");  // 出力: Hello, Alice! そして ALICE!
```


## BiConsumer<T,U> インターフェース

BiConsumer インターフェースは、2つの引数を受け取り、結果を返さない操作を表します。このインターフェースは、関数型インターフェースの一つであり、2つの引数を受け取るConsumerとして考えることができます。このインターフェースはジェネリックを使用しており、`BiConsumer<T, U>` の形式で表されます。

#### 主要なメソッド:


| メソッド名               | 具体的な内容 |
|------------------------|--------------------------------------------------|
| `accept(T t, U u)`     | このメソッドは、2つの引数を受け取り、何らかの操作を実行します。戻り値はvoidです。 |
| `andThen(BiConsumer<? super T, ? super U> after)` | このメソッドは、現在の BiConsumer の操作の後に、別の BiConsumer の操作を実行するためのメソッドです。 |



```
// BiConsumer インターフェースの使用例
BiConsumer<String, Integer> greetAge = (name, age) -> System.out.println("Hello, " + name + "! You are " + age + " years old.");
greetAge.accept("Alice", 25);  // 出力: Hello, Alice! You are 25 years old.

// andThen メソッドの使用例
BiConsumer<String, String> greetCountry = (name, country) -> System.out.println("Hello, " + name + "! You are from " + country + ".");
greetAge.andThen((name, age) -> greetCountry.accept(name, "Japan")).accept("Alice", 25);
// 出力:
// Hello, Alice! You are 25 years old.
// Hello, Alice! You are from Japan.
```

上記のハンズオンでは、BiConsumer インターフェースの主要なメソッドの使用方法を示しています。特に、andThen メソッドを使用して、2つの異なる BiConsumer の操作を連鎖的に実行する方法を示しています。



## BinaryOperator<T> インターフェース
BinaryOperator インターフェースは、2つの同じ型のオペランドに対して操作を実行し、同じ型の結果を返す操作を表します。このインターフェースは Function インターフェースの特殊な形で、`BinaryOperator<T>` の形式で表されます。

### BinaryOperator<T> インターフェース

| メソッド名               | 具体的な内容 |
|------------------------|--------------------------------------------------|
| `apply(T t1, T t2)`    | 2つの引数を受け取り、結果を返します。 |
| `andThen(Function after)` | まず入力にこの関数を適用し、次に結果に関数afterを適用する合成関数を返します。 |
| `compose(Function before)` | まず入力に関数beforeを適用し、次に結果にこの関数を適用する合成関数を返します。 |
| `identity()`           | 常に入力引数を返す関数を返します。 |



```
// BinaryOperator インターフェースの使用例
BinaryOperator<Integer> sum = (a, b) -> a + b;
System.out.println(sum.apply(3, 4));  // 出力: 7
```

## BiPredicate<T,U> インターフェース
BiPredicate インターフェースは、2つの引数を受け取り、boolean値の結果を返す述語（真偽値関数）を表します。このインターフェースはジェネリックを使用しており、`BiPredicate<T, U>` の形式で表されます。

#### 主要なメソッド:


| メソッド名               | 具体的な内容 |
|------------------------|--------------------------------------------------|
| `test(T t, U u)`       | 2つの引数を受け取り、boolean値の結果を返します。 |
| `and(BiPredicate other)` | この述語と別の述語を論理ANDで結合した述語を返します。 |
| `or(BiPredicate other)`  | この述語と別の述語を論理ORで結合した述語を返します。 |
| `negate()`             | この述語の論理否定を返します。 |



```
// BiPredicate インターフェースの使用例
BiPredicate<String, Integer> isNameOfAge = (name, age) -> name.equals("Alice") && age == 25;
System.out.println(isNameOfAge.test("Alice", 25));  // 出力: true
```

## Predicate<T> インターフェース

Predicate インターフェースは、1つの引数を受け取り、boolean値の結果を返す述語を表します。このインターフェースはジェネリックを使用しており、`Predicate<T>` の形式で表されます。

#### 主要なメソッド:

| メソッド名               | 具体的な内容 |
|------------------------|--------------------------------------------------|
| `test(T t)`            | 引数を受け取り、boolean値の結果を返します。 |
| `and(Predicate other)` | この述語と別の述語を論理ANDで結合した述語を返します。 |
| `or(Predicate other)`  | この述語と別の述語を論理ORで結合した述語を返します。 |
| `negate()`             | この述語の論理否定を返します。 |


```
// Predicate インターフェースの使用例
Predicate<String> isNameAlice = name -> name.equals("Alice");
System.out.println(isNameAlice.test("Alice"));  // 出力: true
```

## Supplier<T> インターフェース
Supplier インターフェースは、引数を受け取らず、結果を供給する操作を表します。このインターフェースはジェネリックを使用しており、`Supplier<T>` の形式で表されます。

#### 主要なメソッド:


| メソッド名               | 具体的な内容 |
|------------------------|--------------------------------------------------|
| `get()`                | 結果を供給します |



```
// Supplier インターフェースの使用例
Supplier<String> provideName = () -> "Alice";
System.out.println(provideName.get());  // 出力: Alice
```


## UnaryOperator<T> インターフェース
UnaryOperator インターフェースは、1つのオペランドに対して操作を実行し、同じ型の結果を返す操作を表します。このインターフェースは Function インターフェースの特殊な形で、`UnaryOperator<T>` の形式で表されます。

#### 主要なメソッド:


| メソッド名               | 具体的な内容 |
|------------------------|--------------------------------------------------|
| `apply(T t)`           | 引数を受け取り、結果を返します。 |
| `andThen(Function after)` | まず入力にこの関数を適用し、次に結果に関数afterを適用する合成関数を返します。 |
| `compose(Function before)` | まず入力に関数beforeを適用し、次に結果にこの関数を適用する合成関数を返します。 |
| `identity()`           | 常に入力引数を返す関数を返します。 |


```
// UnaryOperator インターフェースの使用例
UnaryOperator<String> toUpperCase = str -> str.toUpperCase();
System.out.println(toUpperCase.apply("Alice"));  // 出力: ALICE
```