java.util.function以下の関数インターフェース使い方メモ

`java.util.function` パッケージ以下にある関数インターフェースの使い方をメモする。


#`Function<T, R>`
##`apply(T)`
```java:実装例
package java8sample;

import java.util.function.Function;

public class Java8Sample {
    public static void main(String[] args) {
        Function<String, Integer> function = string -> Integer.parseInt(string);
        System.out.println(function.apply("12345"));
    }
}
```

```text:実行結果
12345
```

`Function<T, R>` の抽象メソッド。
`T` 型の引数を受け取って、 `R` 型の値を返す処理を実装する。

##`compose(Function<? super V,? extends T>)`
```java:実装例
package java8sample;

import java.util.function.Function;

public class Java8Sample {
    public static void main(String[] args) {
        Function<String, String> wrapDoubleQuotation = str -> "\"" + str + "\"";
        Function<String, String> wrapSingleQuotation = str -> "'" + str + "'";
        
        Function<String, String> wrapDoubleAndSingleQuotation = wrapDoubleQuotation.compose(wrapSingleQuotation);
        String result = wrapDoubleAndSingleQuotation.apply("hoge");
        
        System.out.println(result);
    }
}
```

```text:実行結果
"'hoge'"
```

`compose()` メソッドを実行した `Function` オブジェクトに、引数で渡した `Function` オブジェクトを組み合わせた新しい `Function` オブジェクトが生成される。

↑の実装は、↓の実装と同じ意味になる。

```java:実装例
package java8sample;

import java.util.function.Function;

public class Java8Sample {
    public static void main(String[] args) {
        Function<String, String> wrapDoubleQuotation = str -> "\"" + str + "\"";
        Function<String, String> wrapSingleQuotation = str -> "'" + str + "'";
        
        String result = wrapDoubleQuotation.apply(wrapSingleQuotation.apply("hoge"));
        
        System.out.println(result);
    }
}
```

`compose(...)` メソッドに渡した `Function` オブジェクトが実行され、その結果が元の `Function` オブジェクトに渡される。


##`andThen(Function<? super R,? extends V>)`
```java:実装例
package java8sample;

import java.util.function.Function;

public class Java8Sample {
    public static void main(String[] args) {
        Function<String, String> wrapDoubleQuotation = str -> "\"" + str + "\"";
        Function<String, String> wrapSingleQuotation = str -> "'" + str + "'";
        
        Function<String, String> wrapDoubleAndSingleQuotation = wrapDoubleQuotation.andThen(wrapSingleQuotation);
        String result = wrapDoubleAndSingleQuotation.apply("hoge");
        
        System.out.println(result);
    }
}
```

```text:実行結果
'"hoge"'
```

`compose()` の逆順序で `Function` オブジェクトが適用される。

##`identity()`
```java:実装例
package java8sample;

import java.util.function.Function;

public class Java8Sample {
    public static void main(String[] args) {
        Function<String, String> function = Function.identity();
        System.out.println(function.apply("string message"));
    }
}
```

```text:実行結果
string message
```

static メソッド。
`apply(T)` メソッドに渡した値をそのまま返す `Function` オブジェクトを生成する。
用途はよくわからない。

#`UnaryOperator<T>`
`Function` の拡張インターフェース。
`Function` の型引数が２つとも同じ型、つまり、引数も戻り値も同じ型を返す特別パターンの `Function`。

```java:実装例
package java8sample;

import java.util.function.UnaryOperator;

public class Java8Sample {
    public static void main(String[] args) {
        UnaryOperator<String> unary = string -> "[" + string + "]";
        System.out.println(unary.apply("hoge"));
    }
}
```

```text:実行結果
[hoge]
```

#`Consumer<T>`
##`accept(T)`
```java:実装例
package java8sample;

import java.util.function.Consumer;

public class Java8Sample {
    public static void main(String[] args) {
        Consumer<String> consumer = string -> System.out.println("Cunsumer : " + string);
        consumer.accept("hoge");
    }
}
```

```text:実行結果
Cunsumer : hoge
```

`Consumer<T>` の抽象メソッド。
`T` 型の値を引数に受け取って、戻り値無しの処理を実装する。

`consumer` の意味は、「消費者」。
戻り値を返さず引数を __消費するだけ__ という感じ？

##`andThen(Consumer<? super T>)`
```java:実装例
package java8sample;

import java.util.function.Consumer;

public class Java8Sample {
    public static void main(String[] args) {
        Consumer<String> hoge = string -> System.out.println("hoge : " + string);
        Consumer<String> fuga = string -> System.out.println("fuga : " + string);
        
        Consumer<String> piyo = hoge.andThen(fuga);
        
        piyo.accept("piyo");
    }
}
```

```text:実行結果
hoge : piyo
fuga : piyo
```

「`andThen()` メソッドを実行した `Consumer` オブジェクト」→「引数で渡した `Consumer` オブジェクト」の順序で処理を実行する新しい `Consumer` オブジェクトが生成される。

#`Supplier<T>`
##`get()`
```java:実装例
package java8sample;

import java.util.function.Supplier;

public class Java8Sample {
    public static void main(String[] args) {
        Supplier<String> supplier = () -> "hoge";
        System.out.println(supplier.get());
    }
}
```

```text:実行結果
hoge
```

`Supplier<T>` の抽象メソッド。
`T` 型の値を返す処理を実装する。

`supplier` の意味は、「供給者」。

#`Predicate<T>`
##`test(T)`
```java:実装例
package java8sample;

import java.util.function.Predicate;

public class Java8Sample {
    public static void main(String[] args) {
        Predicate<String> predicate = string -> string.isEmpty();
        System.out.println(predicate.test(""));
        System.out.println(predicate.test("hoge"));
    }
}
```

```text:実行結果
true
false
```

`Predicate<T>` の抽象メソッド。
`T` 型の値を引数に受け取って、 `boolean` の値を返す処理を実装する。

`predicate` の意味は「断言する」「断定する」。
値の検証を明示するのに使う感じかと。

##`isEqual(Object)`
```java:実装例
package java8sample;

import java.util.function.Predicate;

public class Java8Sample {
    public static void main(String[] args) {
        Predicate<String> isHoge = Predicate.isEqual("hoge");
        System.out.println(isHoge.test("hoge"));
        System.out.println(isHoge.test("fuga"));
        
        Predicate<Object> isNull = Predicate.isEqual(null);
        System.out.println(isNull.test(null));
        System.out.println(isNull.test("not null"));
    }
}
```

```text:実行結果
true
false
true
false
```

引数で受け取ったオブジェクトと等しいかどうかを判定する新しい `Predicate` オブジェクトを生成する（比較は `Object#equals(Object)` メソッドが使用される）。
`null` セーフになっている。

##`and(Predicate<? super T>)`
```java:実装例
package java8sample;

import java.util.function.Predicate;

public class Java8Sample {
    public static void main(String[] args) {
        Predicate<String> isUpperCase = string -> string.matches("[A-Z]+");
        Predicate<String> isAlphabet  = string -> string.matches("[a-zA-Z]+");
        
        Predicate<String> predicate = isAlphabet.and(isUpperCase);
        
        System.out.println(predicate.test("HOGE"));
        System.out.println(predicate.test("hoge"));
    }
}
```

```text:実行結果
true
false
```

引数で渡した `Predicate` オブジェクトを AND 条件で連結させた新しい `Predicate` オブジェクトを生成する。

##`or(Predicate<? super T>)`
```java:実装例
package java8sample;

import java.util.function.Predicate;

public class Java8Sample {
    public static void main(String[] args) {
        Predicate<String> isUpperCase = string -> string.matches("[A-Z]+");
        Predicate<String> isNumber    = string -> string.matches("\\d+");
        
        Predicate<String> predicate = isNumber.or(isUpperCase);
        
        System.out.println(predicate.test("HOGE"));
        System.out.println(predicate.test("1234"));
        System.out.println(predicate.test("hoge"));
    }
}
```

```text:実行結果
true
true
false
```

引数で渡した `Predicate` オブジェクトを OR 条件で連結させた新しい `Predicate` オブジェクトを生成する。

##`negate()`
```java:実装例
package java8sample;

import java.util.function.Predicate;

public class Java8Sample {
    public static void main(String[] args) {
        Predicate<String> isEmpty = string -> string.isEmpty();
        
        Predicate<String> isNotEmpty = isEmpty.negate();
        
        System.out.println(isNotEmpty.test("hoge"));
        System.out.println(isNotEmpty.test(""));
    }
}
```

```text:実行結果
true
false
```

`negate()` を実行した `Predicate` オブジェクトを否定する、新しい `Predicate` オブジェクトが生成される。

#`Bi～`
- `BiConsumer<T,U>`
- `BiFunction<T,U,R>`
- `BiPredicate<T,U>`

それぞれ `Consumer<T>` ・ `Function<T, R>` ・ `Predicate<T, U>` の抽象メソッドの引数が２つになっている。

#`BinaryOperator<T>`
`BiFunction` の拡張インターフェース。
`T` 型の引数を 2 つ受け取って `T` 型の値を返す `apply(T, T)` メソッドが抽象メソッドとして存在する。

##`maxBy(Comparator<? super T>)`
```java:実装例
package java8sample;

import java.util.function.BinaryOperator;

public class Java8Sample {
    public static void main(String[] args) {
        BinaryOperator<Integer> maxBy = BinaryOperator.maxBy(Integer::compare);
        int max = maxBy.apply(21, 10);
        System.out.println(max);
    }
}
```

```text:実行結果
21
```

`apply(T, T)` メソッドに渡された２値を、指定した `Comparator` オブジェクトで比較して大きい方の値を返す `BinaryOperator` オブジェクトを生成する。

##`minBy(Comparator<? super T>)`
```java:実装例
package java8sample;

import java.util.function.BinaryOperator;

public class Java8Sample {
    public static void main(String[] args) {
        BinaryOperator<Integer> minBy = BinaryOperator.minBy(Integer::compare);
        int min = minBy.apply(21, 10);
        System.out.println(min);
    }
}
```

```text:実行結果
10
```

`maxBy()` の逆。

#`To～Function` と `To～BiFunction`
- `ToIntFunction<T>`
- `ToLongFunction<T>`
- `ToDoubleFunction<T>`

それぞれ、 `T` 型の値を引数に受け取って、プリミティブ型の値を返す `applyAs～(T)` 抽象メソッドを持つ。

```java:実装例
package java8sample;

import java.util.function.ToIntFunction;

public class Java8Sample {
    public static void main(String[] args) {
        ToIntFunction<String> getLength = string -> string.length();
        System.out.println(getLength.applyAsInt("hoge"));
    }
}
```

```text:実行結果
4
```

- `ToIntBiFunction<T,U>`
- `ToLongBiFunction<T,U>`
- `ToDoubleBiFunction<T,U>`

それぞれ、 `To～Function` の引数が 2 つになったバージョン。

```java:実装例
package java8sample;

import java.util.function.ToIntBiFunction;

public class Java8Sample {
    public static void main(String[] args) {
        ToIntBiFunction<Integer, Integer> add = (a, b) -> a + b;
        System.out.println(add.applyAsInt(12, 53));
    }
}
```

```text:実行結果
65
```

#`～To***Function`
- `IntToDoubleFunction`
- `DoubleToIntFunction`
- `LongToDoubleFunction`
- `DoubleToLongFunction`
- `IntToLongFunction`
- `LongToIntFunction`

それぞれ `～` を受け取って `***` を返す `applyAs***(～)` メソッドを抽象メソッドとして持つ。

```java:実装例
package java8sample;

import java.util.function.IntToDoubleFunction;

public class Java8Sample {
    public static void main(String[] args) {
        IntToDoubleFunction function = i -> (double)i;
        System.out.println(function.applyAsDouble(20));
    }
}
```

```text:実行結果
20.0
```

#`Obj～Consumer`
- `ObjIntConsumer<T>`
- `ObjLongConsumer<T>`
- `ObjDoubleConsumer<T>`

それぞれ `T` 型の値と `～` の値を引数に受け取る `accept(T, ～)` メソッドを抽象メソッドとして持つ。

```java:実装例
package java8sample;

import java.util.Arrays;
import java.util.List;
import java.util.function.ObjIntConsumer;

public class Java8Sample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hoge", "fuga", "piyo");
        
        forEach(list, (value, index) -> {
            System.out.printf("list[%d] = %s%n", index, value);
        });
    }
    
    public static <T> void forEach(List<T> list, ObjIntConsumer<T> callback) {
        for (int i=0; i<list.size(); i++) {
            callback.accept(list.get(i), i);
        }
    }
}
```

```text:実行結果
list[0] = hoge
list[1] = fuga
list[2] = piyo
```

#参考
- [java.util.function (Java Platform SE 8 b120)](http://download.java.net/jdk8/docs/api/java/util/function/package-summary.html)