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)); } }
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でキー変換する方法」
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();
KHI入社して退社。今はCONFRAGEで正社員です。関西で140-170/80~120万から受け付けております^^
得意技はJS(ES6),Java,AWSの大体のリソースです
コメントはやさしくお願いいたします^^
座右の銘は、「狭き門より入れ」「願わくは、我に七難八苦を与えたまえ」です^^
コメント