Java

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

More than 1 year has passed since last update.

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


Function<T, R>


apply(T)


実装例

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"));
}
}



実行結果

12345


Function<T, R> の抽象メソッド。

T 型の引数を受け取って、 R 型の値を返す処理を実装する。


compose(Function<? super V,? extends T>)


実装例

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);
}
}



実行結果

"'hoge'"


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

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


実装例

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>)


実装例

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);
}
}



実行結果

'"hoge"'


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


identity()


実装例

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"));
}
}



実行結果

string message


static メソッド。

apply(T) メソッドに渡した値をそのまま返す Function オブジェクトを生成する。

用途はよくわからない。


UnaryOperator<T>

Function の拡張インターフェース。

Function の型引数が2つとも同じ型、つまり、引数も戻り値も同じ型を返す特別パターンの Function


実装例

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"));
}
}



実行結果

[hoge]



Consumer<T>


accept(T)


実装例

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");
}
}



実行結果

Cunsumer : hoge


Consumer<T> の抽象メソッド。

T 型の値を引数に受け取って、戻り値無しの処理を実装する。

consumer の意味は、「消費者」。

戻り値を返さず引数を 消費するだけ という感じ?


andThen(Consumer<? super T>)


実装例

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");
}
}



実行結果

hoge : piyo

fuga : piyo

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


Supplier<T>


get()


実装例

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());
}
}



実行結果

hoge


Supplier<T> の抽象メソッド。

T 型の値を返す処理を実装する。

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


Predicate<T>


test(T)


実装例

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"));
}
}



実行結果

true

false

Predicate<T> の抽象メソッド。

T 型の値を引数に受け取って、 boolean の値を返す処理を実装する。

predicate の意味は「断言する」「断定する」。

値の検証を明示するのに使う感じかと。


isEqual(Object)


実装例

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"));
}
}



実行結果

true

false
true
false

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

null セーフになっている。


and(Predicate<? super T>)


実装例

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"));
}
}



実行結果

true

false

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


or(Predicate<? super T>)


実装例

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"));
}
}



実行結果

true

true
false

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


negate()


実装例

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(""));
}
}



実行結果

true

false

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


Bi~


  • BiConsumer<T,U>

  • BiFunction<T,U,R>

  • BiPredicate<T,U>

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


BinaryOperator<T>

BiFunction の拡張インターフェース。

T 型の引数を 2 つ受け取って T 型の値を返す apply(T, T) メソッドが抽象メソッドとして存在する。


maxBy(Comparator<? super T>)


実装例

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);
}
}



実行結果

21


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


minBy(Comparator<? super T>)


実装例

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);
}
}



実行結果

10


maxBy() の逆。


To~FunctionTo~BiFunction


  • ToIntFunction<T>

  • ToLongFunction<T>

  • ToDoubleFunction<T>

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


実装例

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"));
}
}



実行結果

4



  • ToIntBiFunction<T,U>

  • ToLongBiFunction<T,U>

  • ToDoubleBiFunction<T,U>

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


実装例

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));
}
}



実行結果

65



~To***Function


  • IntToDoubleFunction

  • DoubleToIntFunction

  • LongToDoubleFunction

  • DoubleToLongFunction

  • IntToLongFunction

  • LongToIntFunction

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


実装例

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));
}
}



実行結果

20.0



Obj~Consumer


  • ObjIntConsumer<T>

  • ObjLongConsumer<T>

  • ObjDoubleConsumer<T>

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


実装例

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);
}
}
}



実行結果

list[0] = hoge

list[1] = fuga
list[2] = piyo


参考