JDK 8新特性のStream

4410 ワード

Java 8 APIは、ストリームStreamという新しい抽象を追加し、データを宣言的に処理することができます.Streamは、SQL文を使用してデータベースからデータをクエリーするような直感的な方法を使用して、Javaコレクションの演算と表現の高次抽象化を提供します.
Stream APIはJavaプログラマーの生産性を大幅に向上させ、プログラマーに効率的で清潔で簡潔なコードを書くことができます.
このスタイルでは、処理する要素の集合をストリームと見なし、ストリームがパイプ内で伝送され、フィルタリング、ソート、集約など、パイプのノード上で処理することができます.
要素ストリームはパイプ内で中間操作(intermediate operation)の処理を経て、最後に最終操作(terminal operation)によって前の処理の結果を得る.
1.1 Streamとは?
Stream(ストリーム)は、データ・ソースからの要素キューであり、集約操作をサポートします.
  • 要素は、特定のタイプのオブジェクトであり、キューを形成します.JavaのStreamは要素を格納するのではなく、オンデマンドで計算されます.
  • データソースストリームのソース.集合,配列,I/O channel,ジェネレータgeneratorなどであってもよい.
  • 集約操作は、filter、map、reduce、find、match、sortedなどのSQL文のような操作です.

  • 以前のCollection操作とは異なり、Stream操作には2つの基礎的な特徴があります.
  • Pipelining:中間操作はフローオブジェクト自体を返します.これにより、フロースタイル(fluent style)のように複数の操作を1つのパイプに直列に接続できます.これにより、遅延実行(laziness)やショート(short-circuiting)などの操作を最適化できます.
  • 内部反復:以前は集合遍歴はIteratorまたはFor-EAchによって明示的に集合外部で反復されていたが,これを外部反復と呼ぶ.Streamは、ビジターモード(Visitor)によって実現される内部反復を提供する.

  • 1.2生成フロー
    Java 8では、集合インタフェースには、ストリームを生成する2つの方法があります.
  • stream()−コレクションのシリアルストリームを作成する.
  • parallelStream()−は、集合の並列ストリームを作成する.
  • List strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
    //  :            ,        
    List filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
    

    1.3 Streamが提供する方法
    1.3.1 forEach
    Streamは、ストリーム内の各データを反復するための新しい方法「forEach」を提供します.次のコードクリップはforEachを使用して10個の乱数を出力します.
    //  10    ,        
    Random random = new Random();
    random.ints().limit(10).forEach(System.out::println);
    

    1.3.2 map
    mapメソッドは、各要素を対応する結果にマッピングするために使用され、次のコードフラグメントはmapを使用して要素に対応する平方数を出力します.
    List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
    //         ,    ,        
    List squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
    

    1.3.3 filter
    filterメソッドは、設定した条件で要素をフィルタするために使用されます.次のコードクリップはfilterメソッドを使用して空の文字列をフィルタします.
    Liststrings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
    //          
    int count = strings.stream().filter(string -> string.isEmpty()).count();
    

    1.3.4 limit
    limitメソッドは、指定された数のストリームを取得するために使用されます.次のコードクリップはlimitメソッドを使用して10個のデータを印刷します.
    Random random = new Random();
    random.ints().limit(10).forEach(System.out::println);
    

    1.3.5 sorted
    sorted法は対流の並べ替えに用いられる.次のコードクリップはsortedメソッドを使用して出力の10個の乱数をソートします.
    Random random = new Random();
    random.ints().limit(10).sorted().forEach(System.out::println);
    

    1.3.6パラレルプログラム
    parallelStreamはストリームパラレルプロセッサの代替方法である.次の例では、parallelStreamを使用して空の文字列の数を出力します.
    List strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
    //          
    int count = strings.parallelStream().filter(string -> string.isEmpty()).count();
    

    シーケンス実行とパラレルダイレクト切り替えを容易に行うことができます.
    1.3.7 Collectors
    Collectorsクラスは、ストリームを集合および集約要素に変換するなど、多くの帰約操作を実現します.Collectorsは、リストまたは文字列を返すために使用できます.
    Liststrings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
    List filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
     
    System.out.println("    : " + filtered);
    String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
    System.out.println("     : " + mergedString);
    

    1.3.8統計
    また、統計結果を生成するコレクタの中にも非常に役立ちます.これらは主にint、double、longなどの基本タイプに用いられ、以下のような統計結果を生成するために用いることができる.
    List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
     
    IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
     
    System.out.println("        : " + stats.getMax());
    System.out.println("        : " + stats.getMin());
    System.out.println("      : " + stats.getSum());
    System.out.println("    : " + stats.getAverage());
    

    【参考文献】