Java8のStream APIのforEachやfillterやmapやsortedやcollectの使い方

Java8のStream APIのforEachやfillterやmapやsortedやcollectの使い方

Java8からjava.util.stream.Streamというコレクションを便利に操作するクラスができました。

forEach

今まではコレクションをループする時はfor文や拡張for文を使用していましたが、forEachを使えば簡単に記述することができるようになります。

Listのstreamを取得してforEachでループする例です。

import java.util.Arrays;
import java.util.List;

public class StreamSample {
  public  static void main(String[] args) {
    List list = Arrays.asList("C", "C++", "Java", "Scala", "Ruby");
    list.stream().forEach(e -> System.out.println(e));
  }
}

Java8のforEach文の使い方」参照

allMatch

各要素に対して全てが条件を満たすならtrueを返し、そうでなければfalseを返します。

Listのstreamを取得してallMatchで操作する例です。

import java.util.Arrays;
import java.util.List;

public class StreamSample {
  public static void main(String[] args) {
    List<String> list = Arrays.asList("C", "C++", "Java", "Scala", "Ruby");
    boolean flg = list.stream().allMatch(e -> e.contains("C"));
    System.out.println(flg); // false
  }
}

anyMatch

allMatchに対して各要素の一つでも条件を満たすならtrue、全ての要素が条件を満たさないならfalseを返します。

import java.util.Arrays;
import java.util.List;

public class StreamSample {
  public static void main(String[] args) {
    List<String> list = Arrays.asList("C", "C++", "Java", "Scala", "Ruby");
    boolean flg = list.stream().anyMatch(s -> s.contains("C"));
    System.out.println(flg); // true
  }
}

noneMatch

noneMatchメソッドは、全要素がfalseの場合trueとなり、一つでもtrueの場合、falseとなります。

import java.util.stream.Stream;

public class NoneMatchSample {
  public static void main(String[] args) {
    Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
    boolean bool = stream.noneMatch(e -> e > 5); // 全てfalseの場合、true
    System.out.println(bool); // true
    stream = Stream.of(1, 2, 3, 4, 5);
    bool = stream.noneMatch(e -> e >= 5); // 1つでもtrueの場合、false
    System.out.println(bool); // false
  }
}

filter

filterは中間操作です。filterはその名の通り、条件を満たす要素のみにフィルタリングします。

import java.util.Arrays;
import java.util.List;

public class StreamSample {
  public static void main(String[] args) {
    List<String> list = Arrays.asList("C", "C++", "Java", "Scala", "Ruby");
    list.stream().filter(s -> s.contains("C"))
                 .forEach(System.out::println);
  }
}

filterの引数に、文字列::equalsというメソッド参照なども記述することが出来ます。

import java.util.Arrays;
import java.util.List;

public class StreamSample {
  public static void main(String[] args) {
    final List<String> list = Arrays.asList("C", "C++", "Java", "Scala", "Ruby");
    list.stream().filter("Java"::equals).forEach(System.out::println); // Java
  }
}

メソッド参照の否定は、!"Java"::equalsとすることはできません。

Predicate.not(“Java”::equals)としてメソッド参照の否定となります。

import java.util.Arrays;
import java.util.List;

public class StreamSample {
  public static void main(String[] args) {
    final List<String> list = Arrays.asList("C", "C++", "Java", "Scala", "Ruby");
    list.stream().filter(Predicate.not("Java"::equals)).forEach(System.out::println);
  }
}

map

mapは中間操作です。mapは各要素を別の型に変換してくれます。以下はString型の各要素をInteger型に変換している例です。

import java.util.Arrays;
import java.util.List;

public class StreamSample {
  public static void main(String[] args) {
    List<String> list = Arrays.asList("2","4","3","02");
    list.stream().map(Integer::parseInt)
                 .forEach(System.out::println);
  }
}

mapで変換処理をしますが、以下は2倍にする例です。

import java.util.function.Function;
import java.util.stream.Stream;

public class StreamSample {
  public static void main(String[] args) {
    Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
    Function<Integer, Integer> mapping = e -> e * 2;
    Stream<Integer> ret = stream.map(mapping);
    ret.forEach(e -> {
      System.out.println(e);
    });
  }
}

・mapToInt

・sum

オブジェクトをプリミティブ型に変換するメソッドです。以下はプリミティブ型に変換してsumメソッドで合計している例です。

import java.util.Arrays;
import java.util.List;

public class StreamSample {
  public static void main(String[] args) {
    List<String> list = Arrays.asList("2","4","3","02");
    int count = list.stream().mapToInt(Integer::parseInt)
                             .sum();
    System.out.println(count);
  }
}

distinct

各要素で重複している要素を取り除くメソッドです。

import java.util.Arrays;
import java.util.List;

public class StreamSample {
  public static void main(String[] args) {
    List<String> list = Arrays.asList("C","C++","C","Java","java");
    list.stream().distinct()
      .forEach(System.out::println);
  }
}

sorted

sortedは中間操作です。

各要素を昇順にソートします。

import java.util.Arrays;
import java.util.List;

public class StreamSample {
  public static void main(String[] args) {
    List<String> list = Arrays.asList("3","2","8","4","1");
    list.stream().sorted()
                 .forEach(System.out::println);
  }
}

降順でソートするにはComparatorを使います。

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamSample {
  public static void main(String[] args) {
    List<String> ret = Stream.of("3", "2", "8" ,"4" , "1")
      .sorted(Comparator.reverseOrder()) // 降順にするにはsortedに引数が必要
      .collect(Collectors.toList()); // 注
    ret.forEach((e)->{
      System.out.println(e);
    });
  }
}

peek

peekは中間操作です。終端操作があって初めて評価されますが、peek自体はどういう値が入っているかなどを調べたい場合に使うメソッドです。

import java.util.Arrays;
import java.util.List;

public class StreamSample {
  public static void main(String[] args) {
    List<Integer> list = Arrays.asList(3,2,8,4,1);
    list.stream().filter(i -> i > 3).peek(x -> System.out.println(x))
                                    .count();
  }
}

collect

collectメソッドは色々中間操作をしたのちに最終的にコレクションを返します。

メソッド 戻り値
toList List<T>
toMap Map<K,V>
groupingBy Map<K,V>
joining String(文字列連結)
maxBy 最大値(Optional)
minBy 最小値(Optional)
toSet Set<T>

Collectors.toList

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class StreamSample {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("c");
    list.add("d");
    List<String> ret = list.stream().filter((r) -> {return !r.equals("a");}).collect(Collectors.toList()); // 注
    System.out.println(ret);    
    ret.forEach(e -> System.out.println(e));
  }
}

結果は以下のようになります。

[b, c, d]
b
c
d

Collectors.toMap

collectメソッドの引数にCollectors.toMapを指定して、Map<K,V>に変換します。

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import jp.co.data.Employee;

public class StreamSample {
  public static void main(String[] args) {
    final List<Employee> list = new ArrayList<>();
    list.add(new Employee("takahashi", 40));
    list.add(new Employee("adachi", 20));

    final Map<String, Integer> result =
    list.stream().collect(Collectors.toMap(k -> k.getName(), v -> v.getAge()));
    result.entrySet().stream().forEach(System.out::println);
  }
}

結果は以下のようになります。

adachi=20
takahashi=40

Java8のCollectors.toMap()の使い方

Java8のMap Stream APIでキー変換する方法

Java8でEnumをStreamに変換する方法

Collectors.joining(引数1つ)

collectメソッドのに引数にCollectors.joining(“区切り文字”)を指定して、文字列連結します。

これはコレクションがStringの場合に限ります。

import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamSample {
  public static void main(String[] args) {
    Stream<String> stream = Stream.of("1", "2", "3", "4", "5");
    String i = stream.collect(Collectors.joining("-")); // ハイフン区切りで連結する
    System.out.println(i);
  }
}

結果は以下のようになります。

1-2-3-4-5

Collectors.joining(引数3つ)

collectメソッドのに引数にCollectors.joining(“区切り文字”,”先頭文字”,”末尾文字”)を指定して、文字列連結します。

連結した文字列を{と}で囲み、各要素をカンマ区切りします。

import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamSample {
  public static void main(String[] args) {
 final Stream<String> stream = Stream.of("1", "2", "3", "4", "5");
final String i = stream.collect(Collectors.joining(",", "{", "}"));
System.out.println(i); // {1,2,3,4,5}
  }
}

Collectors.groupingBy

Collectors.groupingByメソッドを使うことによってグルーピングすることができます。

以下は文字列長が同じ文字列でグルーピングする例です。

import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamSample {
  public static void main(String[] args) {
    Stream<String> stream = Stream.of("aiu", "eo", "eeee", "eeaa", "ai", "aiu", "a", "aio"); // 文字列長でグルーピングする
    stream.collect(Collectors.groupingBy(String::length)).forEach((k,v) -> {
      System.out.println(k + " = " + v);
    });
  }
}

結果は以下のようになります。List<V>をMap<K, V>に変換してくれます。

1 = [a]
2 = [eo, ai]
3 = [aiu, aiu, aio]
4 = [eeee, eeaa]

Collectors.maxBy

Collectors.maxByメソッドを使うことによって最大値を求めます。引数にComparatorを指定します。

import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamSample {
  public static void main(String[] args) {
    final Optional<Integer> ret =
    Stream.of(3, 2, 8, 4, 1).collect(Collectors.maxBy((c1, c2) -> c1 - c2));
    System.out.println(ret.get()); // 8
  }
}

Collectors.minBy

Collectors.minByメソッドを使うことによって最小値を求めます。引数にComparatorを指定します。

import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamSample {
  public static void main(String[] args) {
    final Optional<Integer> ret =
      Stream.of(3, 2, 8, 4, 1).collect(Collectors.minBy((c1, c2) -> c1 - c2));
    System.out.println(ret.get()); // 1
  }
}

toArray

toArrayメソッドでObject[]を返します。

import java.util.ArrayList;
import java.util.List;

import jp.co.data.Employee;

public class StreamSample {
  public static void main(String[] args) {
    final List<Employee> list = new ArrayList<>();
    list.add(new Employee("takahashi", 40));
    list.add(new Employee("adachi", 20));

    final Object[] fields = list.stream().map(e -> e.getName()).toArray();
    for (final Object field : fields) {
      System.out.println(field); // takahashi adachi
    }
  }
}

引数にString[]::newというように指定するとString[]配列を返します。

Java8のStreamでPOJOのフィールド名を配列にする方法

count

countメソッドでstreamの件数を返します。

import java.util.ArrayList;
import java.util.List;

import jp.co.data.Employee;

public class StreamSample {
  public static void main(String[] args) {
    final List<Employee> list = new ArrayList<>();
    list.add(new Employee("takahashi", 40));
    list.add(new Employee("adachi", 20));

    final long cnt = list.stream().count(); // 2
    System.out.println(cnt);
  }
}

summaryStatistics

summaryStatisticsメソッドでIntSummaryStatisticsのインスタンスを返します。

このクラスは計算するメソッドが用意されています。

import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;

public class StreamSample {
  public static void main(String[] args) {
    final List<String> list = Arrays.asList("C", "C++", "Java", "Scala", "Ruby");
    final IntSummaryStatistics result = list.stream().mapToInt(e -> e.length()).summaryStatistics();
    System.out.println("最大値: " + result.getMax()); // 最大値: 5
    System.out.println("最小値: " + result.getMin()); // 最小値: 1
    System.out.println("平均値: " + result.getAverage()); // 平均値: 3.4
    System.out.println("件数: " + result.getCount()); // 件数: 5
  }
}

リスト同士を結合する

Stream.concatメソッドでリスト同士を結合する

リスト同士をStream.concatメソッドでマージすることができます。

package jp.co.confrage;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamSample {
  public static void main(String[] args) {
    List<String> list1 = new ArrayList<>();
    list1.add("test1");
    list1.add("test2");
    List<String> list2 = new ArrayList<>();
    list2.add("test1");
    list2.add("test2");
    list2.add("test3");
    List<String> ret = Stream.concat(list1.stream(),list2.stream())
      .sorted()
      .collect(Collectors.toList()); // 注
    ret.forEach(e -> {
      System.out.println(e);
    });
  }
}

重複した結果が返ります。

test1
test1
test2
test2
test3

flatMapメソッドでリスト同士を結合する

flatMapメソッドを使用してリストを結合することもできます。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamSample {
  public static void main(String[] args) {
    final List<String> list1 = new ArrayList<>();
    list1.add("test1");
    list1.add("test2");
    final List<String> list2 = new ArrayList<>();
    list2.add("test1");
    list2.add("test2");
    list2.add("test3");
    final List<List<String>> input = Arrays.asList(list1, list2);
    final List<String> ret = input.stream().flatMap(e -> e.stream()).collect(Collectors.toList()); // 注
    ret.forEach(e -> {
      System.out.println(e);
    });
  }
}

limitで件数を絞る

limitメソッドで件数を指定します。引数はlong型なので3Lというように最後にLを付けます。

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamSample {
  public static void main(String[] args) {
    List<String> ret = Stream.of("3", "2", "8" ,"4" , "1")
      .sorted().limit(3L) // 昇順でソートして3件だけにする
      .collect(Collectors.toList()); // 注
    ret.forEach((e)->{
      System.out.println(e);
    });
  }
}

ソートされた結果を3件だけにしています。

1
2
3

FindAny

Java8のStream API findAnyメソッドで任意の要素を取得する

FindFirst

Java8のStream API findFirstメソッドで一番最初の要素を取得する

注:Java16から以下メソッド追加されました。

.collect(Collectors.toList());

.toList();

コメント

株式会社CONFRAGE ITソリューション事業部をもっと見る

今すぐ購読し、続きを読んで、すべてのアーカイブにアクセスしましょう。

続きを読む

タイトルとURLをコピーしました