1
1

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 3 years have passed since last update.

【Java】Stream API - ストリーム中間処理

Posted at

ストリーム中間処理

  • ストリームを流れる値を加工、フィルターする
  • 実行されるのは終端処理が呼ばれたタイミング

指定条件で値をフィルタ

  • filterメソッド
import java.util.stream.Stream;
public class Main {
  public static void main(String[] args) {
    Stream.of(
      "https://qiita.com/",
      "Neko",
      "CAT",
      "https://www.amazon.co.jp/",
      "https://ja.wikipedia.org/wiki/Neko_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2)"
    )
      .filter(s -> s.startsWith("https://"))
      .forEach(System.out::println);
/*
https://qiita.com/
https://www.amazon.co.jp/
https://ja.wikipedia.org/wiki/Neko_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2)
*/
  }
}

与えられた値を加工

  • mapメソッド
  • 文字列リストを文字列長リストに変換して出力
  • 生成された直後はString<String>で、mapメソッドを経たらString<Integer>になる
import java.util.stream.Stream;
public class Main {
  public static void main(String[] args) {

    Stream.of("Munchkin", "Siamese", "Persian", "Scottish Fold", "Tama")
    .map(s -> s.length())
    .forEach(System.out::println); //8 7 7 13 4
  }
}
  • 基本型ストリームを生成するmapToInt/mapToLong/mapToDoubleメソッド
  • String<Integer>ではなくIntStreamが生成される
  • ボクシングの負担減少
import java.util.stream.Stream;
public class Main {
  public static void main(String[] args) {
    Stream.of("Munchkin", "Siamese", "Persian", "Scottish Fold", "Tama")
    .mapToInt(s -> s.length())
    .forEach(System.out::println); //8 7 7 13 4
  }
}

与えられた要素を加工

  • flatMap/flatMapToXXメソッド
  • 変換結果をStream型で返すのがmapとの違い
  • 個々の要素で返したStreamが最終的に結合されて返る
//二次元配列listを一次元配列に変換
import java.util.Arrays;
public class Main {
  public static void main(String[] args) {

    var list = new String[][] {
      { "neko", "nekko", "nekkko" },
      { "inu", "innu" },
      { "tori", "torri" }
    };
    //flatMapで入れ子の配列を渡し、Arrays.streamメソッドでストリーム化
    //flatMapで連結することで一次元配列にフラット化
    Arrays.stream(list)
      .flatMap(v -> Arrays.stream(v))
      .forEach(System.out::println);
     // neko nekko nekkko inu innu tori torri
    }
}
  • ストリーム加工の際に入れ子で値を加工することも可能
//二次元配列をフラット化する際に頭文字を取り出す
import java.util.Arrays;
public class Main {
  public static void main(String[] args) {

    var list = new String[][] {
      { "neko", "nekko", "nekkko" },
      { "inu", "innu" },
      { "tori", "torri" }
    };

    Arrays.stream(list)
    .flatMap(v -> Arrays.stream(v).map(str -> str.substring(0, 1)))
    .forEach(System.out::println);
    //n n n i i t t
    }
}

要素を並び替える

  • sortedメソッド
  • 自然順序によるソート
import java.util.stream.Stream;
public class Main {
  public static void main(String[] args) {

    Stream.of("Munchkin", "Siamese", "Persian", "Scottish Fold", "Tama")
    .sorted()
    .forEach(System.out::println);
// Munchkin
// Persian
// Scottish Fold
// Siamese
// Tama
  }
}
  • 規則を設定したい場合、ラムダ式で設定
import java.util.stream.Stream;
import java.util.Comparator;

public class Main {
  public static void main(String[] args) {

    Stream.of("Munchkin", "Siamese", "Persian", "Scottish Fold", "Tama")
    .sorted((str1, str2) -> str1.length() - str2.length())
    .forEach(System.out::println);
    // Tama
    // Siamese
    // Persian
    // Munchkin
    // Scottish Fold

    /*Comparatorインターフェースで辞書逆順
     Stream.of("Munchkin", "Siamese", "Persian", "Scottish Fold", "Tama")
     .sorted(Comparator.reverseOrder())
     .forEach(System.out::println);
    */
  }
}

m~n番目の要素を取り出す

  • skip/limitメソッド
  • skipメソッド:m番目までの要素を切り捨てる
  • limitメソッド:n+1番目以降の要素を切り捨てる
//skipで4要素をスキップし、limitでそこから10個分の要素を取り出す
import java.util.stream.IntStream;
public class StreamLimit {
  public static void main(String[] args) {
    IntStream.range(1, 20)
      .skip(4)
      .limit(10)
      .forEach(System.out::println); //5,6,7,8,9,10,11,12,13,14
  }
}

先頭から条件をみたす間の値を除去

  • dropWhileメソッド
  • 条件式に合致してる値をスキップ
    • ストリームの先頭から負数を除去
    • あくまでも先頭から連続する値なので途中の負数は除去しない
    • →途中の場合はfilterで除去
import java.util.stream.IntStream;
public class StreamDrop {
  public static void main(String[] args) {
    IntStream.of(-2, -5, 0, 3, -1, 2)
      .dropWhile(i -> i < 0)
      .forEach(System.out::println); //0,3,-1,2
  }
}

先頭から条件を満たす間の値のみ取り出す

  • takeWhileメソッド
  • ストリームの先頭から負数であるものだけを処理する
    • あくまでも処理するのは先頭から連続する値
import java.util.stream.IntStream;
public class StreamTake {
  public static void main(String[] args) {
    IntStream.of(-2, -5, 0, 3, -1, 2)
      .takeWhile(i -> i < 0)
      .forEach(System.out::println); //-2,-5
  }
}

ストリームの途中状態を確認する

  • peekメソッド
  • 途中で任意の処理を挟むことができる
  • peekメソッドはストリームに影響を及ぼさない
//ソート前後でストリーム内容を出力
import java.util.stream.Stream;
public class StreamPeek {
  public static void main(String[] args) {
    Stream.of("さかな", "あか", "こだま", "きんもくせい")
      .peek(System.out::println)
      .sorted()
      .forEach(System.out::println);
  }
}

値の重複を除去

  • distinctメソッド
  • ストリームに含まれる値の重複を除去
  • 任意のクラスの特定フィールドをキーに重複除去できない
  • →filterメソッドを使う
import java.util.stream.Stream;
public class Main {
  public static void main(String[] args) {
    Stream.of("ねこ", "猫", "ねっこ", "ねこ", "ねこねこ")
      .distinct()
      .forEach(System.out::println);
    // ねこ
    // 猫
    // ねっこ
    // ねこねこ
  }
}
  • Personクラスでnameフィールドをキーに重複をチェック
import java.util.HashSet;
import java.util.stream.Stream;

public class StreamDistinctObj {

  public static void main(String[] args) {
    var set = new HashSet<String>();
    Stream.of(
        new Person("山田", 40),
        new Person("高野", 30),
        new Person("大川", 35),
        new Person("山田", 45)
      )
      //filterメソッドの中で値をHashSetに追加
      //HashSet.addメソッドは値を追加できなかった(重複)場合falseを返す

      .filter(p -> set.add(p.name))
      .forEach(System.out::println);
  }
}
public class Person {
  public String name;
  public int age;

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }
  @Override
  public String toString() {
    return String.format("%s(%d歳)", this.name, this.age);
  }
}

基本型ストリームの変換

  • asLongStream/asDoubleStream/LongStreamで型変換
//IntStreamからDoubleStreamへの変換
import java.util.stream.IntStream;
public class Main {
  public static void main(String[] args) {
    IntStream.range(1, 5)
      .asDoubleStream()
      .forEach(System.out::println);
      //1.0 2.0 3.0 4.0
  }
}

基本型、参照型ストリームを相互変換

  • 基本型から参照型:boxedメソッド
  • 参照型から基本型:mapToObjメソッド
//IntStreamからStream<Integer>に変換
import java.util.stream.IntStream;
public class Main {
  public static void main(String[] args) {
    IntStream.range(1, 5)
      .boxed()
      .forEach(System.out::println);
      //1 2 3 4
      
    IntStream.range(1, 5)
      .mapToObj(Integer::valueOf)
      .forEach(System.out::println);
      //1 2 3 4
  }
}
//Stream<Integer>からIntStreamに変換
import java.util.stream.Stream;
public class StreamUnboxed {
  public static void main(String[] args) {
    Stream.of(1, 2, 3, 4)
      .mapToInt(i -> i) //アンボクシングでInteger→int
      .forEach(System.out::println); //1 2 3 4
    }
}
1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?