Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Java8 stream APIサンプルコード

More than 5 years have passed since last update.

概要

Java8 Stream APIを使用したサンプルコードです。

サンプルコード

streamインスタンス

streamインスタンスを取得するサンプルコードです。

java.util.stream.Stream#of

Stream
Stream<String> stream = Stream.of("A","B","C","D","E");

java.util.Arrays#stream

Arrays
Stream<String> stream = Arrays.stream(new String[]{"A","B","C","D","E"});

java.util.Collection#stream

Collection
List<String> list = Arrays.asList("A","B","C","D","E");
Stream<String> stream = list.stream();

java.lang.CharSequence#chars

CharSequence
String str = "ABCDE";
IntStream streamf = str.chars();

Stream#forEach

理解を助けるために同じ処理について関数インターフェースを実装する方法、ラムダ式を使う方法、メソッド参照を使う方法で記述しました。

関数インターフェースを実装する例

forEach
Stream<String> streamf = Arrays.stream(new String[]{"A","B","C","D","E"});

streamf.forEach(new Consumer<String>() {
  @Override
  public void accept(String name) {
    System.out.println(name);
  }
});

ラムダ式で実装する例

forEach
streaml.forEach((final String name) -> System.out.println(name));

ラムダ式は状況によってコードを簡略化することができます。
上記のコードはコンパイラの型推論によって、下記のように引数の型情報を省略することができます。

forEach
streaml.forEach((name) -> System.out.println(name));

さらに引数が1つの場合は丸カッコを省略することができます。

forEach
streaml.forEach(name -> System.out.println(name));

メソッド参照で実装する例

さらにコード全体をメソッド参照に置き換えることができます。

forEach
streaml.forEach(System.out::println);

Stream#forEach (その2)

文字列のコレクションを加工した結果を別のコレクションへ保存するサンプルコードです。
forEachメソッドの戻り値はありませんので、処理結果を受け取りたい場合はメソッドの外で定義した変数を使用します。

関数インターフェースを実装する例

forEach
Stream<String> streamf = Stream.of("A","B","C","D","E");

final List<String> resultf = new ArrayList<>();

streamf
  .forEach(new Consumer<String>() {
    @Override
    public void accept(final String name) {
      String tmp = name.toLowerCase();
      System.out.println(tmp);
      resultf.add(tmp);
    }
  });

System.out.println(resultf);
// ⇒ [a, b, c, d, e]

ラムダ式で実装する例

forEach
Stream<String> streaml = Stream.of("A","B","C","D","E");

final List<String> resultl = new ArrayList<>();

streaml
  .forEach(name -> {
    String tmp = name.toLowerCase();
    System.out.println(tmp);
    resultl.add(tmp);
  });

System.out.println(resultl);
// ⇒ [a, b, c, d, e]

Stream#map, Stream#collect

文字列のコレクションを加工した結果を別のコレクションへ保存するサンプルコードです。
上記のforEachメソッドを使った例と処理内容は同じですが、外部の変数を必要としない点で副作用がありません。

関数インターフェースを実装する例

collectメソッドの

  • 第1引数のSupplierは、処理結果を格納する型(コンテナ)のインスタンスを生成する処理を記述します。
  • 第2引数のBiConsumerは、Supplierで生成したインスタンスへ処理結果を格納する処理を記述します。
  • 第3引数のBiConsumerは、処理結果を格納したインスタンスを他のインスタンスにまとめる処理を記述します。
map_collect
Stream<String> streamf = Arrays.stream(new String[]{"A","B","C","D","E"});

final List<String> resultf =
  streamf
    .map(new Function<String, String>() {
      @Override
      public String apply(final String s) {
        return s.toLowerCase();
      }
    })
    .collect(
      new Supplier<List<String>>() {
        @Override
        public List<String> get() {
          return new ArrayList<String>();
        }},
      new BiConsumer<List<String>, String>() {
        @Override
        public void accept(final List<String> t, final String s) {
          t.add(s);
        }
      },
      new BiConsumer<List<String>, List<String>>() {
        @Override
        public void accept(final List<String> t, final List<String> u) {
          t.addAll(u);
        }
      }
    );

System.out.println(resultf);
// ⇒ [a, b, c, d, e]

ラムダ式で実装する例

map_collect
Stream<String> streaml1 = Arrays.stream(new String[]{"A","B","C","D","E"});

final List<String> resultl1 =
  streaml1
    .map(s -> s.toLowerCase())
    .collect(
      () -> new ArrayList<String>(),
      (t, s) -> t.add(s),
      (t, u) -> t.addAll(u)
    );

System.out.println(resultl1);
// ⇒ [a, b, c, d, e]

メソッド参照で実装する例

(注) ArrayList::newはコンストラクタ参照です。

map_collect
Stream<String> streaml2 = Arrays.stream(new String[]{"A","B","C","D","E"});

final List<String> resultl2 =
  streaml2
    .map(String::toLowerCase)
    .collect(ArrayList<String>::new, ArrayList<String>::add, ArrayList<String>::addAll);

System.out.println(resultl2);
// ⇒ [a, b, c, d, e]

CollectorsクラスのtoListメソッドで下記のように書き換えることができます。
ちなみにtoListの他にもtoMapやtoSetなどがあります。

map_collect
Stream<String> streaml3 = Arrays.stream(new String[]{"A","B","C","D","E"});

final List<String> resultl3 =
  streaml3
    .map(String::toLowerCase)
    .collect(Collectors.toList());

System.out.println(resultl3);
// ⇒ [a, b, c, d, e]

他の例になりますが、Collectors#joiningで文字列の結合処理を簡単に記述できます。

Stream<String> streaml = Arrays.stream(new String[]{"A","B","C","D","E"});

String resultl =
  streaml
    .map(String::toLowerCase)
    .collect(Collectors.joining(",","[","]"));

System.out.println(resultl);
// ⇒ [a,b,c,d,e]

Stream#filter, Stream#reduce

数値のコレクションから条件に一致するデータの合計を得るサンプルコードです。

関数インターフェースを実装する例

filter_reduce
List<Integer> list = Arrays.asList(30, 110, -30, 70, 20, -10, 60);

Stream<Integer> streamf = list.stream();

Integer sumf =
  streamf
    .filter(new Predicate<Integer>() {
      @Override
      public boolean test(final Integer t) {
        return t >= 0;
      }
    })
    .reduce(new BinaryOperator<Integer>() {
      @Override
      public Integer apply(final Integer t, final Integer u) {
        return t + u;
      }
    })
    .get();

System.out.println(sumf);
// ⇒ 290

ラムダ式で実装する例

filter_reduce
List<Integer> list = Arrays.asList(30, 110, -30, 70, 20, -10, 60);

Stream<Integer> streaml = list.stream();

Integer suml =
  streaml
    .filter(t -> t >= 0)
    .reduce((t,u) -> t + u)
    .get();

System.out.println(suml);
// ⇒ 290

Stream#distinct

コレクションから重複するデータを除いたコレクションを生成するサンプルコードです。

ラムダ式で実装する例

distinct
Stream<String> stream = Arrays.stream(new String[]{"A","a","B", "B", "b", "C", "D", "DD", "E"});

final List<String> result =
  stream
    .map(s -> s.toLowerCase())
    .filter(s -> s.length() == 1)
    .distinct()
    .collect(Collectors.toList());

System.out.println(result);
// ⇒ [a, b, c, d, e]

Stream#flatMap

複数のstreamを1つに束ねて処理するサンプルコードです。

関数インターフェースで実装する例

flatMap
List<List<String>> list = new ArrayList<>();

List<String> list1 = Arrays.asList("A", "B", "C", "D", "E");
List<String> list2 = Arrays.asList("a", "b", "c", "d", "e");
List<String> list3 = Arrays.asList("あ", "い", "う", "え", "お");

list.add(list1);
list.add(list2);
list.add(list3);

Stream<String> streamf =
  list.stream().flatMap(new Function<List<String>, Stream<? extends String>>() {
    @Override
    public Stream<? extends String> apply(List<String> t) {
      return t.stream();
    }
  });
List<String> resultf = streamf.collect(Collectors.toList());

System.out.println(resultf);
// ⇒ [A, B, C, D, E, a, b, c, d, e, あ, い, う, え, お]

ラムダ式で実装する例

flatMap
List<List<String>> list = new ArrayList<>();

List<String> list1 = Arrays.asList("A", "B", "C", "D", "E");
List<String> list2 = Arrays.asList("a", "b", "c", "d", "e");
List<String> list3 = Arrays.asList("あ", "い", "う", "え", "お");

list.add(list1);
list.add(list2);
list.add(list3);

Stream<String> streaml =
  list.stream().flatMap(l -> l.stream());
List<String> resultl = streaml.collect(Collectors.toList());

System.out.println(resultl);
// ⇒ [A, B, C, D, E, a, b, c, d, e, あ, い, う, え, お]

Stream#flatMap (その2)

関数インターフェースで実装する例

flatMap
Map<Integer, List<String>> map = new HashMap<>();

List<String> list1 = Arrays.asList("A", "B", "C", "D", "E");
List<String> list2 = Arrays.asList("a", "b", "c", "d", "e");
List<String> list3 = Arrays.asList("あ", "い", "う", "え", "お");

map.put(1, list1);
map.put(2, list2);
map.put(3, list3);

Stream<Entry<Integer, List<String>>> stream1 = map.entrySet().stream();

Stream<String> streamf = 
  stream1.flatMap(new Function<Entry<Integer, List<String>>, Stream<? extends String>>() {
    @Override
    public Stream<? extends String> apply(Entry<Integer, List<String>> t) {
      return t.getValue().stream();
    }
  });
List<String> resultf = streamf.collect(Collectors.toList());

System.out.println(resultf);
// ⇒ [A, B, C, D, E, a, b, c, d, e, あ, い, う, え, お]

ラムダ式で実装する例

flatMap
Map<Integer, List<String>> map = new HashMap<>();

List<String> list1 = Arrays.asList("A", "B", "C", "D", "E");
List<String> list2 = Arrays.asList("a", "b", "c", "d", "e");
List<String> list3 = Arrays.asList("あ", "い", "う", "え", "お");

map.put(1, list1);
map.put(2, list2);
map.put(3, list3);

Stream<Entry<Integer, List<String>>> stream2 = map.entrySet().stream();

Stream<String> streaml =
  stream2.flatMap(m -> m.getValue().stream());
List<String> resultl = streaml.collect(Collectors.toList());

System.out.println(resultl);
// ⇒ [A, B, C, D, E, a, b, c, d, e, あ, い, う, え, お]

リファレンスメモ

java.util.stream

package

Interface Stream

Class Collectors

java.lang

Interface Iterable

java.util

Class Arrays

Interface Collection

java.util.function

package

Interface Supplier<T>

method
T get()

Interface Predicate<T>

method
boolean test(T t)

Interface Consumer<T>

Type Parameters:
T - the type of the input to the operation

method
void accept(T t)

Interface Function<T,R>

Type Parameters:
T - the type of the input to the function
R - the type of the result of the function

method
R apply(T t)
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away