LoginSignup
19
25

More than 5 years have passed since last update.

StreamAPIの基本

Last updated at Posted at 2017-02-16

はじめに

・StreamAPIの代表的なメソッドと、基本的なコーディング例を示します。
・StreamAPIの考え方や応用例、テクニックについては他のエントリーへ委譲し、ここではできるだけシンプルに書くように努めます。
・Streamはラムダ式またはメソッド参照を与えて書くのが一般的ですが、あえて関数型インタフェースを宣言します。

StreamAPIとは

・SE8で追加された、データの集合を扱うためのAPI。主な目的は並列処理への対応。StreamAPIを用いると、順次処理から並行処理への切替えが容易になる。

・java.util.streamパッケージ配下のインタフェースのことであり、java.ioパッケージで用いるストリームとは別物。

・java.util.streamパッケージは、BaseStreamインタフェースを基底として、参照型を扱うためのStreamインタフェースと、プリミティブ型を扱うための3つのインタフェースにより構成される。

・StreamはListやMapなどのデータ集合をもとに生成し、0回以上の中間操作と、1回の終端操作を実行することで結果を得る。

より詳しく

Java(tm) Platform Standard Edition 8 パッケージ java.util.stream
Java Stream APIをいまさら入門 - 基本編
Java8 Streamざっくりまとめ

生成

参照型Stream

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream();

プリミティブ型Stream

IntStream intStream = IntStream.of(1, 2, 3, 4, 5);

配列から

int[] array = { 1, 2, 3, 4, 5 };
IntStream intStream = Arrays.stream(array);

レンジを指定して

IntStream intStream = IntStream.range(1, 5);

ファイルから

Path path = Paths.get("D:\\hoge.txt");
Stream<String> fileStream = Files.lines(path)

最も単純なStream操作

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream();
stream.forEach(System.out::println);

Integer型のStreamを生成し、中間操作0回、終端操作1回で、標準出力処理を実行する。
forEachは終端操作。終端操作については後述。
基本的には、これに任意の回数の様々な中間操作と、同じく様々な終端操作のうちいずれか1回を組み合わせて利用する。

より詳しく

Java 8 Stream API にテキストを流してみる(生成編)

中間操作

フィルタリング

Stream<String> stream = Stream.of("A", "B", "A", "B", "B", "A");
Predicate<String> isA = "A"::equals;
stream.filter(isA).forEach(System.out::println);

Predicate型のisHogeHogeを間に掛けてFalseを間引くイメージ。
Predicateは関数型インタフェース。
関数型インタフェースについては以下。
3分でわかる基本の関数型インタフェース

マッピング

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Function<Integer, Integer> toDouble = param -> param * 2;
stream.map(toDouble).forEach(System.out::println);

Streamの各要素をキーとして、対応する値のStreamを返す。
要は変換処理みたいなもの。
サンプルはわかりやすくFunctionを使ったが、この場合はUnaryOperatorがスマート。
ラムダ式については以下。
Java8 Lambdaの文法拡張まとめ
インタフェースの実装がラムダになるまで

ソート

Stream<Integer> stream = Stream.of(3, 2, 1, 5, 4);
Comparator<Integer> comparator = Comparator.reverseOrder();
stream.sorted(comparator).forEach(System.out::println);

sortedにcomparatorを与えることで、順序を指定する。
Comparatorについては以下。
(o1, o2) -> o1 - o2 なんて呪文はもうやめて! - Java8でのComparatorの使い方

終端操作

マッチング

Stream<String> stream = Stream.of("George", "John", "Ringo", "Paul");
Predicate<String> isRingo = "Ringo"::equals;
boolean isMatch = stream.anyMatch(isRingo);

allMatch、noneMatchなどのバリエーションもある。

カウント

Stream<String> countSt = Stream.of("George", "John", "Ringo", "Paul");
long result = countSt.count();

リダクション

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream();
BinaryOperator<Integer> sum = Integer::sum;
Optional<Integer> result = stream.reduce(sum);

畳み込みなど、結果を単一の値へ処理する。
戻り値はOptional。Optionalについては以下。
Java 8 "Optional" ~ これからのnullとの付き合い方 ~

可変リダクション

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream();
List<Integer> resultList = stream.collect(Collectors.toCollection(ArrayList::new));
resultList.forEach(System.out::print);

ArrayListなど、集合へ処理する。

より詳しく

Java 8 Stream API にテキストを流してみた(終端操作編)
Java8 Streamのリダクション操作について

並列処理

Stream<String> stream= Stream.of("A", "B", "C", "D", "E", "F");
stream.parallel().forEach(param -> System.out.println(param + " thread-id: " + Thread.currentThread().getId()));

生成時にpararelStream()を使うか、中間操作でparallel()を噛ませるだけで並列処理になる。

より詳しく

さあ、並列プログラミングをはじめよう
Java8のStreamとParallelStreamの使い分けについて
streamとparallelStreamについての考察
Java それぞれ書き方でどれほどパフォーマンスが違うのか?計測比較してみた。Streamとループとか

並列処理は書ききれないので深くは触れません。

19
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
25