Stream便利だなーと思ったので、まとめてみます。
Streamの作成
Of
Streamを返す。
要素に対しての型指定も可能。
// 直接作成
Stream stream = Stream.of("a", "b", "c", "d", "e");
IntStream intStream = IntStream.of(1, 2, 3, 4, 5);
DoubleStream doubleStream = DoubleStream.of(1.0, 2.0, 3.0, 4.0, 5.0);
LongStream longStream = LongStream.of(1, 2, 3, 4, 5);
変換
主要な型からstreamに変換。
// Listから変換
List<String> list = Arrays.asList("a", "b", "c", "d", "e");
Stream listStrem = list.stream();
// Mapから変換
Map<Integer, String> map = new HashMap<>();
map.put(1, "A");
map.put(2, "B");
map.put(3, "C");
Stream<Map.Entry<Integer, String>> mapStream = map.entrySet().stream();
// 文字列から変換
String str = "ABCDE";
IntStream strStream = str.chars();
Builder
Streamのビルダーを返す。
Stream.Builder<Integer> sb = Stream.builder();
sb.add(10);
sb.add(20);
Stream<Integer> buildStream =sb.build();
buildStream.forEach(System.out::println);
10
20
Generate
順序付けされていない無限順次ストリームを返す。
Stream<Integer> stream = Stream.generate(() -> 1);
stream.limit(3).forEach(System.out::println);
1
1
1
ランダムな値を生成する場合などに使いたい。
例:0~9までのランダムな値を5個返す。
Stream.generate(Math::random).limit(5).map(s -> Math.floor(s * 10)).mapToInt(Double::intValue).forEach(System.out::println);
2
2
9
6
8
Iterate
順序付けされた無限順次Streamを返す。
Stream<Integer> stream = Stream.iterate(1, x -> x * 2);
stream.limit(5).forEach(System.out::println);
1
2
4
8
16
concat
Streamを結合する。
Stream<String> stream1 = Stream.of("a", "b");
Stream<String> stream2 = Stream.of("c", "d", "e");
Stream.concat(stream1,stream2).forEach(System.out::println);
a
b
c
d
e
empty
空のStreamを作成。
Stream<?> emptyList = Stream.empty();
emptyList.forEach(System.out::println);
No OutPut
要素の取得
ラムダ式やメソッド参照を使用するとスッキリ書ける。
文字列に関しては、戻り型がIntStream型
のためmapToObj
メソッドで型変換を行う必要がある。
// Stream型
// ラムダ式
Stream.of("a", "b", "c", "d", "e").forEach(s -> System.out.println(s));
// メソッド参照
Stream.of("a", "b", "c", "d", "e").forEach(System.out::println);
//List
Arrays.asList(1, 2, 3, 4, 5).stream().forEach(System.out::println);
//Map
Map<Integer, String> map = new HashMap<>();
map.put(1, "A");
map.put(2, "B");
map.put(3, "C");
map.entrySet().stream().forEach(s -> System.out.println("key: " + s.getKey() + " value: " + s.getValue()));
//文字列
String str = "ABCDE";
str.chars().mapToObj(s -> (char)s)
.forEach(System.out::println);
数値範囲
range
// 末尾を含まない
IntStream.range(1,5).forEach(System.out::println);
1
2
3
4
###rangeClosed
// 末尾を含む
IntStream.rangeClosed(1,5).forEach(System.out::println);
1
2
3
4
5
中間操作
要素を変換する
map
ラムダで処理を書ける。
Stream.of(1, 2, 3, 4, 5).map(s -> s * 2).forEach(System.out::println);
2
4
6
8
10
mapToInt
mapToLong
,mapToDouble
も使い方は同じ。
Stream.of("1", "2", "3", "4", "5") // Stream<String>
.mapToInt(s -> Integer.parseInt(s)) // IntStream
.map(s -> s * 2)
.forEach(System.out::println);
2
4
6
8
10
flatMap
1対Nで変換できる。
// flatMap
Stream<String> stream1 = Stream.of("A", "BB", "CCC", "DDDD", "EEEEE");
stream1.flatMap(s -> Stream.of(s, s.length(), s.toLowerCase())).forEach(System.out::print);
A1aBB2bbCCC3cccDDDD4ddddEEEEE5eeeee
要素を絞り込む
filter
Stream.of(10, 20, 30, 40, 50).filter(s -> s <= 30).forEach(System.out::println);
10
20
30
skip & limit
skip
Stream.of(10, 20, 30, 40, 50).skip(2).forEach(System.out::println);
30
40
50
limit
Stream.of(10, 20, 30, 40, 50).limit(2).forEach(System.out::println);
10
20
skip & limit
skip
とlimit
を組み合わせることで範囲を指定できる。
Stream.of(10, 20, 30, 40, 50).skip(2).limit(2).forEach(System.out::println);
30
40
distinct
重複を取り除く。
Stream.of("A", "A", "B", "B", "B", "C").distinct().forEach(System.out::println);
A
B
C
要素を並べ換える
sorted
// sorted
Stream.of(13, 52, 34, 6, 28).sorted((s1, s2) -> s1 - s2).forEach(System.out::println);
// Comparatorオブジェクトを使用
Stream.of(13, 52, 34, 6, 28).sorted(Comparator.comparingInt(s -> s)).forEach(System.out::println);
6
13
28
34
52
デバック
peek
デバック出力用のメソッド。streamに関して何も影響を及ぼさない。
List<String> numbers = Stream.of("one", "two", "three", "four")
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());
Filtered value: three
Mapped value: THREE
Filtered value: four
Mapped value: FOUR
終端操作
結果を出力する
forEach
繰り返し処理を行う。ラムダ式を用いて、操作を書くことができる。
下の例を書いて見たが、mapで書き直せる...。
Stream.of(10, 20, 30, 40 ,50).forEach(s -> {
int intResult = s / 10;
System.out.println(intResult);
});
forEachOrdered
並列処理を行う際に順序通りに出力できる。forEach
を使用するとランダムな順序で出力される。
parallelStream()
は並列処理用のstream。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
System.out.println("--------forEach---------");
list.parallelStream().filter(s -> s > 1).forEach(System.out::println);
System.out.println("--------forEachOrdered---------");
list.parallelStream().filter(s -> s > 1).forEachOrdered(System.out::println);
forEachはランダムに出力されるのに対し、forEachOrderedはリストの順序通りに出力される。
--------forEach---------
3
5
4
2
--------forEachOrdered---------
2
3
4
5
結果を取り出す
collect
様々な型で結果を返す。
list
// list型で返却
List<String> list = Stream.of("A", "B", "C", "D", "E").collect(Collectors.toList());
System.out.println(list);
[A, B, C, D, E]
String
//String型で返却
String join1 = Stream.of("A", "B", "C", "D", "E").collect(Collectors.joining());
System.out.println(join1);
String join2 = Stream.of("A", "B", "C", "D", "E").collect(Collectors.joining(","));
System.out.println(join2);
ABCDE
A,B,C,D,E
Map
Group化したものをMapで返却してくれる。
//最低限のモデルクラス
public class Score {
private String name;
private int score;
public Score(String name, int score){
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public int getScore() {
return score;
}
}
// scoreListを作成
List<Score> scoreList = new ArrayList<>();
scoreList.add(new Score("Tanaka", 90));
scoreList.add(new Score("Suzuki", 80));
scoreList.add(new Score("Nakamura", 100));
scoreList.add(new Score("Ito", 90));
scoreList.add(new Score("Hamanaka", 100));
//グループ分け
Map<Integer, List<Score>> map = scoreList.stream().collect(Collectors.groupingBy(Score::getScore));
//Mapの要素を出力
map.entrySet().stream().forEach(s -> System.out.println("Key: " + s.getKey() + ", Value:" + s.getValue()));
//scoreが100点のスコアデータを表示
List<Score> score100 = map.get(100);
score100.forEach(s -> System.out.println("name: " + s.getName() + ", score: " + s.getScore()));
返却されたMapはグループ化されて、Valueに対応するStreamがリスト化されている。
# Mapの要素を出力
Key: 80, Value:[com.example.javalearn.qiita.stream.Score@446cdf90]
Key: 100, Value:[com.example.javalearn.qiita.stream.Score@799f7e29, com.example.javalearn.qiita.stream.Score@4b85612c]
Key: 90, Value:[com.example.javalearn.qiita.stream.Score@277050dc, com.example.javalearn.qiita.stream.Score@5c29bfd]
# scoreが100点のスコアデータを表示
name: Nakamura, score: 100
name: Hamanaka, score: 100
toArray
Streamを配列に変換する。
String[] toArray = Stream.of("a", "b", "c", "d", "e").toArray(String[]::new);
for(String s:toArray){
System.out.println(s);
}
a
b
c
d
e
reduce
結果を累積する。
int total = Stream.of(1, 2, 3, 4, 5).reduce((a,b) -> a + b).get();
System.out.println(total);
//メソッド参照も可能
int total1 = Stream.of(1, 2, 3, 4, 5).reduce(Integer::sum).get();
やっていることとしては、以下のようなことである。
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
10 + 5 = 15
15
結果を絞り込む
findFirst
リストの最初の要素を取り出す。
String findFirst = Stream.of("A", "B", "C", "D", "E").findFirst().orElse("null");
System.out.println(findFirst);
A
max
Integer max = Stream.of(1, 2, 3, 4, 5).max(Comparator.naturalOrder()).orElse(0);
System.out.println(max);
5
min
Integer min = Stream.of(1, 2, 3, 4, 5).min(Comparator.naturalOrder()).orElse(0);
System.out.println(min);
1
sum
Integer sum = IntStream.of(1, 2, 3, 4, 5).sum();
System.out.println(sum);
15
count
Long count = Stream.of(1, 2, 3, 4, 5).count();
System.out.println(count);
5
average
Double average = IntStream.of(1, 2, 3, 4, 5).average().orElse(0);
System.out.println(average);
3.0
結果を検索する
anyMatch
部分一致
Boolean anyMatch1 = Stream.of(1, 2, 3, 4, 5).anyMatch(s -> s > 2);
Boolean anyMatch2 = Stream.of(1, 2, 3, 4, 5).anyMatch(s -> s < 0);
System.out.println(anyMatch1);
System.out.println(anyMatch2);
true
false
allMatch
完全一致
Boolean allMatch1 = Stream.of("one", "two", "three", "four").allMatch(s -> s.length() <= 5);
Boolean allMatch2 = Stream.of("one", "two", "three", "four").allMatch(s -> s.length() <= 4);
System.out.println(allMatch1);
System.out.println(allMatch2);
true
false
noneMatch
完全不一致
Boolean noneMatch1 = Stream.of("one", "two", "three", "four").noneMatch(s -> s.length() <= 2);
Boolean noneMatch2 = Stream.of("one", "two", "three", "four").noneMatch(s -> s.length() <= 4);
System.out.println(noneMatch1);
System.out.println(noneMatch2);
true
false