社内se × プログラマ × ビッグデータ

プログラミングなどITに興味があります。

java.util.stream のソースを読んでみる filter 編

stream については、package java.util.stream; の JavaDoc には以下のように書かれています。

 * A sequence of elements supporting sequential and parallel aggregate
 * operations.

並んでいる要素に対して、直列または並列処理をサポートするみたいなイメージでしょうか。

そもそも、Java8 ではなぜ List から stream() を使って Stream に変換が出来るのだろう?
> Collection インタフェースに stream() が用意されていて、List ではそれを継承しているようです。
https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html

では、filter の JavaDoc を見てみます。

    /**
     * Returns a stream consisting of the elements of this stream that match
     * the given predicate.
     *
     * <p>This is an <a href="package-summary.html#StreamOps">intermediate
     * operation</a>.
     *
     * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
     *                  <a href="package-summary.html#Statelessness">stateless</a>
     *                  predicate to apply to each element to determine if it
     *                  should be included
     * @return the new stream
     */
    Stream<T> filter(Predicate<? super T> predicate);

うーん。Predicate ですか。
では、Predicate の JavaDoc を見てみます。

/**
 * Represents a predicate (boolean-valued function) of one argument.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #test(Object)}.
 *
 * @param <T> the type of the input to the predicate
 *
 * @since 1.8
 */

これだけでは、ピンと来なかったですが、用意されているメソッドを見てみると、test(T t) というものがあります。

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);

与えられた引数が条件(直訳だと述語?)に一致した場合は、true 一致しない場合は false を返します。
interface Predicate は他にもメソッドが定義されていますが、最終的にこの test(T t) が呼ばれるようです。

つまり、Stream filter(Predicate predicate); の中の Predicate predicate に関しては
与えたデータ型 T が boolean に変換されるとも捉えられるので、
Stream filter(T -> boolean);
こんな感じに変換(おおざっぱに)捉えることにします。

例として、

List<String> before = Arrays.asList("a", "b", "c");
List<String> after = before.stream().filter(e -> e.equals("b")).collect(Collectors.toList());
after.forEach(System.out::println); // b

filter(T -> boolean) と filter(e -> e.equals("b")) のような関係にこじつけられます。