前置き
Java SE8の関数型インタフェースやStreamのプリミティブ特殊化についてまとめました。
目的はJava Gold試験対策です。
プリミティブ特殊化とは
javaでは、Function<T,R>のR apply(T t) のT,Rのような型引数にはプリミティブを与えることができない。関数型インタフェースやStreamにおいては、int、long、doubleについても(ラッパークラスにボクシングせずに)ジェネリクスっぽく操作ができるように、個別にクラスがいくつか定義されている。これをプリミティブ特殊化を行った型という。
intだけ覚えておけばlong, doubleも差異は無い。
関数型インターフェイスの整理
java.util.functionの全関数型インタフェース
基本のクラス名 | intへの特殊化 | longへの特殊化 | doubleへの特殊化 | 基本のメソッド名 |
---|---|---|---|---|
Function<T,R> | IntFunction<R> | LongFunction<R> | DoubleFunction<R> | apply() |
Function<T,R> | IntToDoubleFunction | LongToDoubleFunction | DoubleToIntFunction | apply() |
Function<T,R> | IntToLongFunction | LongToIntFunction | DoubleToLongFunction | apply() |
Function<T,R> | ToIntFunction<T> | ToLongFunction<T> | ToDoubleFunction<T> | apply() |
UnaryOperator<T> | IntUnaryOperator | LongUnaryOperator | DoubleUnaryOperator | apply() |
BiFunction<T,U,R> | ToIntBiFunction<T,U> | ToLongBiFunction<T,U> | ToDoubleBiFunction<T,U> | apply() |
BinaryOperator<T> | IntBinaryOperator | LongBinaryOperator | DoubleBinaryOperator | apply() |
Predicate<T> | IntPredicate | LongPredicate | DoublePredicate | test() |
BiPredicate<T,U> | - | - | - | test() |
Consumer<T> | IntConsumer | LongConsumer | DoubleConsumer | accept() |
BiConsumer<T,U> | ObjIntConsumer<T> | ObjLongConsumer<T> | ObjDoubleConsumer<T> | accept() |
Supplier<T> | IntSupplier | LongSupplier | DoubleSupplier | get() |
BooleanSupplier | - | - | - | getAsBoolean() |
ポイント
-
プリミティブ特殊化された関数型インタフェースは、プリミティブ特殊化されたStreamのメソッドの引数として現れる。
- e.g.
IntStream.filter()の引数にIntPredicateを取るなど。
- e.g.
-
関数型インタフェースのメソッド名は、戻り値がプリミティブの場合にだけ、 「基本のメソッド名As型名」 とする。
- e.g.
- R apply(T t) →戻り値をintに→ int applyAsInt(T t)
- T get() →戻り値をdoubleに→ double getAsDouble()
- e.g.
-
特殊化の対象は基本的にint, long, doubleのみで、BooleanSupplierは特別。
- BooleanSupplierはたぶんテストやアサーションを書くときに使う想定なのかな。
- 「悪いなfloat、このパッケージは3人用なんだ」
-
Functionのプリミティブ特殊化は、次の各パターンに対応している。
- プリミティブの引数をとってプリミティブを返す
- オブジェクトの引数をとってプリミティブを返す
- プリミティブの引数をとってオブジェクトを返す
-
表の2,3行目で、IntToIntFunctionはないの?となりそうだが、それはIntUnaryOperator。
-
BiConsumerに対応するObjIntConsumerのaccept()は、引数1がオブジェクトで引数2がintとなっている。
これはIntStream.collect()のアキュムレータとして使う。
java.util.streamのプリミティブ特殊化の整理
種類
Stream<T>からプリミティブ特殊化された型は以下の3クラス。
- IntStream
- LongStream
- DoubleStream
ここでは仮にプリミティブ特殊化ストリームと呼ぶことにします。
プリミティブ特殊化ストリーム特有の終端操作
- sum() : 和をとる。
- avarage() : 算術平均をとる。戻り値はOptionalDouble。
- max() : 順序が自明なので、Stream<T>.max(Comparator)と異なり引数を取らない。
- min() : 順序が自明なので、Stream<T>.min(Comparator)と異なり引数を取らない。
Stream<T>とプリミティブ特殊化ストリームの相互変換
プリミティブ特殊化ストリームから
mapToXxx()メソッド
this | 戻り値 | メソッド名 | 引数 |
---|---|---|---|
IntStream | LongStream | mapToLong *1 | IntToLongFunction |
IntStream | DoubleStream | mapToDouble *1 | IntToDoubleFunction |
IntStream | Stream<T> | mapToObj *2 | IntFunction<? extends T> |
LongStream | IntStream | mapToInt | LongToIntFunction |
LongStream | DoubleStream | mapToDouble *1 | LongToDoubleFunction |
LongStream | Stream<T> | mapToObj *2 | LongFunction<? extends T> |
DoubleStream | IntStream | mapToInt | DoubleToIntFunction |
DoubleStream | LongStream | mapToLong | DoubleToLongFunction |
DoubleStream | Stream<T> | mapToObj *2 | DoubleFunction<? extends T> |
*1 単なるアップキャストは、asXxx()メソッドでできる
this | 戻り値 | メソッド名 | 引数 |
---|---|---|---|
IntStream | DoubleStream | asDoubleStream | - |
IntStream | LongStream | asLongStream | - |
LongStream | DoubleStream | asDoubleStream | - |
*2 単なるボクシングは、boxed()メソッドでできる
this | 戻り値 | メソッド名 | 引数 |
---|---|---|---|
IntStream | Stream<Integer> | boxed | - |
LongStream | Stream<Long> | boxed | - |
DoubleStream | Stream<Double> | boxed | - |
Stream<T>からプリミティブ特殊化ストリームへ
mapToXxx()メソッド
this | 戻り値 | メソッド名 | 引数 |
---|---|---|---|
Stream<T> | IntStream() | mapToInt | ToIntFunction<? super T> |
Stream<T> | LongStream() | mapToLong | ToLongFunction<? super T> |
Stream<T> | DoubleStream() | mapToDouble | ToDoubleFunction<? super T> |
flatMapToXxx()メソッド
平坦化とプリミティブ特殊化の組み合わせ。いかにも試験に出そうなやつ。
this | 戻り値 | メソッド名 | 引数 |
---|---|---|---|
Stream<T> | IntStream() | flatMapToInt | Function<? super T,? extends IntStream> |
Stream<T> | LongStream() | flatMapToLong | Function<? super T,? extends LongStream> |
Stream<T> | DoubleStream() | flatMapToDouble | Function<? super T,? extends DoubleStream> |
追加すべきものがあったら教えてください。