Java Gold ラムダ式(関数)について

# ラムダ式とは何か
ラムダ式は、匿名関数（名前を持たない関数）を簡潔に表現するための構文です。従来、匿名クラスを使用して記述していたコードを、よりシンプルに書くことができます。これにより、コードの可読性が向上し、開発効率もアップします。

例：匿名クラスとラムダ式の比較

```java
// 匿名クラスを使用
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello, World!");
    }
};

// ラムダ式を使用
Runnable runnable = () -> System.out.println("Hello, World!");
```
# ラムダ式の基本構文
ラムダ式の基本的な構文は以下のとおりです。


```rust
(引数リスト) -> { 処理内容 }
```

引数リスト：関数が受け取る引数をカンマで区切って列挙します。
矢印演算子（->）：ラムダ式であることを示します。
処理内容：メソッドの本体を中括弧 {} 内に記述します。

`シンプルな例`

```java
// 引数なし、戻り値なし
() -> System.out.println("Hello, Lambda!");

// 引数あり、戻り値なし
(String message) -> System.out.println(message);

// 引数あり、戻り値あり
(int x, int y) -> x + y;
省略可能な部分
```

引数の型はコンパイラが推論できる場合、省略可能。
引数が1つの場合、括弧 () を省略可能。
処理内容が単一の式の場合、中括弧 {} と return キーワードを省略可能。

`省略例`

```java
// 型と括弧を省略
message -> System.out.println(message);
// 中括弧とreturnを省略
(x, y) -> x + y;
```
# 関数型インターフェース
ラムダ式は関数型インターフェースを実装するために使用されます。関数型インターフェースとは、抽象メソッドを1つだけ持つインターフェースのことです。

代表的な関数型インターフェース

```Consumer<T>```：引数を1つ取り、戻り値なし。（コンシューマー）
`Function<T, R>`：引数を1つ取り、戻り値あり。（ファンクション）
`Predicate<T>`：引数を1つ取り、boolean を返す。（プレディケート）
    `Supplier<T>`：引数なし、戻り値あり。        （サプライヤー）
`Comparator<T>`：2つの引数を取り、整数を返す。（コンパレーター）

# 早見表
| メソッド                 | 役割                                 | 使用する関数型インターフェース        |
|--------------------------|--------------------------------------|---------------------------------------|
| **forEach**              | 各要素に対する処理                  | Consumer< T >                           |
| **map**                  | 各要素の変換                        | Function< T , R >                        |
| **filter**               | 条件に合う要素を抽出                | Predicate< T >                          |
| **sort**                 | 要素の並べ替え                      | Comparator< T >                         |
| **reduce**               | 要素の集約                          | BinaryOperator< T >                     | 
| **ifPresent**            | 値が存在する場合の処理              | Consumer< T >                           |
| **submit (スレッド)**    | タスクの非同期実行                  | Runnable or Callable< V >           |
| **collect(toMap)**       | リストやセットをマップに変換        | Function< T , K >, Function< T, V >      |
| **peek**                 | 各要素に処理を行い、ストリームを返す | Consumer< T >                           |
| **allMatch**             | すべての要素が条件を満たすか判定    | Predicate< T >                          |
| **anyMatch**             | いずれかの要素が条件を満たすか判定  | Predicate< T >                          |
| **noneMatch**            | すべての要素が条件を満たさないか判定| Predicate< T >                          |
| **findFirst**            | 最初の要素を取得                    | Supplier<Optional<　T　>>                 |
| **findAny**              | 任意の要素を取得（並列処理に適用）  | Supplier< Optional < T > >                 |
| **max**                  | 最大値を取得                        | Comparator< T >                         |
| **min**                  | 最小値を取得                        | Comparator< T >                         |
| **groupingBy**（Collectors） | グループ化しマップに変換           | Function< T , K >                        |
| **partitioningBy**（Collectors） | 条件で2つのグループに分ける    | Predicate< T >                          |
| **flatMap**              | 要素を展開して一つのストリームにする | Function< T, Stream< R>>               |




# ラムダ式の活用例
#### コレクションの操作
`forEachメソッド`
コレクションの各要素に対して処理を行います。

```java
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));
```
`sortメソッド`
リストの要素を特定の基準で並べ替えます。

```java
names.sort((a, b) -> a.length() - b.length());
```
# ストリームAPIとの連携
`mapメソッド`
各要素に関数を適用して、新しいストリームを生成します。

```java
List<Integer> nameLengths = names.stream()
    .map(name -> name.length())
    .collect(Collectors.toList());
```
`filterメソッド`
条件に合致する要素だけを抽出します。

```java
List<String> shortNames = names.stream()
    .filter(name -> name.length() <= 3)
    .collect(Collectors.toList());
```
`reduceメソッド`
ストリームの要素を集約して1つの結果にまとめます。

```java
int totalLength = names.stream()
    .map(name -> name.length())
    .reduce(0, (a, b) -> a + b);
```
# 並行処理での使用
`Runnable`（ラナブル）と`Callable`（カラブル）
スレッドやタスクの実行で使用されます。

```java
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> System.out.println("Task is running"));
executor.shutdown();
```
# Optionalクラスとの組み合わせ
`ifPresentメソッド`（イフプレゼント）
値が存在する場合に処理を実行します。

```java
Optional<String> optionalName = Optional.of("Alice");
optionalName.ifPresent(name -> System.out.println("Name: " + name));
```
`mapメソッド`
Optionalの値を変換します。

```java
Optional<Integer> nameLength = optionalName.map(name -> name.length());
```

# メソッド参照とラムダ式
ラムダ式が既存のメソッドをそのまま呼び出すだけの場合、メソッド参照を使用してより簡潔に記述できます。

シンタックス
`ClassName::methodName`
`object::methodName`


```java
// ラムダ式を使用
names.forEach(name -> System.out.println(name));

// メソッド参照を使用
names.forEach(System.out::println);
```