8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Java Streamについてのまとめ

Posted at

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
skiplimitを組み合わせることで範囲を指定できる。

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で返却してくれる。

Score.java
//最低限のモデルクラス
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

参考

Stream (Java Platform SE 8 )

8
6
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
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?