Stream API(Java 8)について少し

Java8Stream APIを使用する例が記載された短い記事です 。これは、初心者ユーザーが機能を学習して使用するのに役立つことを願っています。






多くの場合、 Java8Stream APIを使用してコレクションを操作し、機能的なスタイルでコードを記述できます。

メソッドの利便性とシンプルさは、リリース以来、開発者の間でこの機能に関心を寄せています。
では、Java8のStream APIとは何ですか? 「パッケージjava.util.stream」- 「コレクションのmap-reduce変換など、要素のストリームで機能スタイルの操作をサポートするクラス 独自のバージョンの翻訳を提供しようとします。実際、これは、処理されたデータの処理や「折りたたみ」など、フローに対する操作の機能スタイルのサポートです。


「ストリーム操作は中間操作と端末操作に分けられ、組み合わされてストリームパイプラインを形成します。 ストリームパイプラインは、ソース(コレクション、配列、ジェネレーター関数、I / Oチャネルなど)で構成されます。 Stream.filterやStream.mapなどの0個以上の中間操作が続きます。 およびStream.forEachやStream.reduceなどの端末操作」 - サイトからの説明

この定義を理解してみましょう。 著者は、コンベヤーの形で組み合わされる中間および最終操作の存在について教えてくれます。 ストリームコンベヤには、ソース(たとえば、コレクションなど)が含まれ、その後に中間および最終操作と例が示されます。 スレッド上のすべての中間操作は遅延(LAZY)であることに注意してください。 これらは、ターミナル(最終)操作が呼び出されるまで実行されません。


別の興味深い機能はparallelStream()の存在です。 これらの機能を使用して、大量のデータを処理するときのパフォーマンスを向上させます。 並列フローは、特定のタイプの操作の実行を高速化します。 コレクションがForkJoinバージョンで処理するのに十分な大きさであることがわかっている場合、この機会を利用します。 ForkJoinの詳細については、このトピックに関する以前の記事「Java 8の並列化。 サブタスクを作成し、その実装を監視することを学んでいます。」


理論的な部分を終了し、簡単な例に進みます。

この例は、コレクションから最大値と最小値を見つけることを示しています。

/** *  № 1 *      */ ArrayList<Integer> testValues = new ArrayList(); testValues.add(0,15); testValues.add(1,1); testValues.add(2,2); testValues.add(3,100); testValues.add(4,50); Optional<Integer> maxValue = testValues.stream().max(Integer::compareTo); System.out.println("MaxValue="+maxValue); Optional<Integer> minValue = testValues.stream().min(Integer::compareTo); System.out.println("MinValue="+minValue);
      
      





例を少し複雑にして、例2の最大値を持つ例外(nullの形式)を追加しましょう。

 /** *  № 2 *     null  */ ArrayList<Integer> testValuesNull = new ArrayList(); testValuesNull.add(0,null); testValuesNull.add(1,1); testValuesNull.add(2,2); testValuesNull.add(3,70); testValuesNull.add(4,50); Optional<Integer> maxValueNotNull = testValuesNull.stream().filter((p) -> p != null).max(Integer::compareTo); System.out.println("maxValueNotNull="+maxValueNotNull);
      
      





例を複雑にしましょう。 「名前」フィールドと「スポーツキャンプの日数」フィールドで構成されるコレクション「スポーツキャンプ」を作成しましょう。 以下のクラスを作成する例。

 public class SportsCamp { private String name; //  private Integer day; //     public SportsCamp(String name, int day) { this.name = name; this.day = day; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getDay() { return day; } public void setDay(Integer day) { this.day = day; } }
      
      





そして今、新しいデータを扱う例:

 import java.util.Arrays; import java.util.Collection; public class Start { public static void main(String[] args) { Collection<SportsCamp> sport = Arrays.asList( new SportsCamp("Ivan", 5), new SportsCamp("Petr", 7), new SportsCamp("Ira", 10) ); /** *  3 *          */ String name = sport.stream().max((p1,p2) -> p1.getDay().compareTo(p2.getDay())).get().getName(); System.out.println("Name="+name); } }
      
      





この例では、名前が見つかりました。イリーナは、キャンプに長く滞在します。

サンプルを変換し、エラーが入り込み、名前の1つのエントリがnullである状況を作成します。

 Collection<SportsCamp> sport = Arrays.asList( new SportsCamp("Ivan", 5), new SportsCamp( null, 15), new SportsCamp("Petr", 7), new SportsCamp("Ira", 10) );
      
      





この場合、「Name = null」に等しい結果が得られます。これは望ましくないことに同意します。コレクションの検索を新しいオプションに少し変更します。

 /** *  № 4 */ String nameTest = sport.stream().filter((p) -> p.getName() != null).max((p1, p2) -> p1.getDay().compareTo(p2.getDay())).get().getName();
      
      





結果、「イラ」は正しいです。

これらの例は、null値の例外の形で、わずかに追加されたコレクションの最小値と最大値を見つけることを示しています。

前述のように、使用可能なメソッドは、中間操作と最終操作の2つの大きなグループに分けることができます。 著者はそれらを別の方法で呼び出すことができます。たとえば、名前コンベヤーとターミナルメソッドの変形が文献や記事で使用されています。 メソッドを使用する場合、1つの設計機能があり、多くの中間操作を「スロー」して、最後に1つのターミナルメソッドを呼び出すことができます。

新しい例では、特定の要素の並べ替えと出力を追加します。たとえば、「Ivan」が発生する名前でフィルターを追加し、そのような要素のカウントを実行します(null値を除く)。

 /** *  № 5 */ long countName = sport.stream().filter((p) -> p.getName() != null && p.getName().equals("Ivan")).count(); System.out.println("countName="+countName);
      
      





新しいSportsCamp(「Ivan」、17)をコレクションに追加すると、「countName = 2」に等しい結果が得られます。 2つのエントリが見つかりました。

これらの例では、コレクションからのストリームの作成を使用しました。他のオプションを使用できます。たとえば、必要な値からストリームを作成します。たとえば、Stream streamFromValues = Stream.of(“ test1”、“ test2”、“ test3”)、他のオプションが可能です

前述のように、ユーザーはparallelStream()を使用して「処理」を使用する機会があります。

例を少し変更することで、新しい実装オプションが得られます:

 long countNameParallel = sport.parallelStream().filter((p) -> p.getName() != null && p.getName().equals("Ivan")).count(); System.out.println("countNameParallel=" + countNameParallel);
      
      





このオプションの機能は、並列ストリームの実装です。 parallelStream()は、大規模なコレクションの強力なサーバー(マルチコア)で正当に使用されていることに注意してください。 コレクションの明確な定義と正確なサイズは示していません。 多くのパラメータを特定して計算する必要があります。 多くの場合、テストのみがパフォーマンスの向上を示すことができます。

簡単な操作に少し慣れて、パイプライン操作とターミナル操作の違いを理解し、両方を試しました。 次に、より複雑な操作の例を見てみましょう。たとえば、収集とマップ、フラット化、および削減です。

もう一度、公式のドキュメントドキュメントを見て、サンプルを実装してみてください。

新しい例では、「I」で始まる名前でコレクションを別のコレクションに変換し、リストに書き込みます。

 List<SportsCamp> onlyI = sport.stream().filter(p -> p.getName() != null && p.getName().startsWith("I")).collect(Collectors.toList()); System.out.println("SIZE="+onlyI.size());
      
      





結果は3つになります。 ここでは、null要素の例外を指定する順序が重要であることに注意する必要があります。

コレクターには、平均値の出力や統計付きの情報など、多くの機能があることに注意してください。 例として、次のようにデータを接続してみましょう。

 String campPeople = sport.stream().filter(p -> p.getName() != null).map(SportsCamp::getName).collect(Collectors.joining(" and ","In camp "," rest all days.")); System.out.println(campPeople);
      
      





結果:「キャンプではイヴァンとペトル、イヴァンとイラは一日中休んでいます。」 Collectors.joiningにはいくつかの用途があります。


Map、Flat、およびReduceから、reduceの例を詳しく見てみましょう。 マップとフラットマップについては、今後の記事で説明します。

Reduceは、ストリーム内の他の要素のインジケーターを集約してオブジェクトの新しいインスタンスを作成する場合、単純な言語で要素を「アセンブル」するために使用され、reduceが適しています。 いくつかのユースケースがあります。 たとえば、そのうちの1つを考えてみましょう。スポーツキャンプでの滞在のすべての日のデータをまとめます。

 Integer daySum = sport.stream().reduce(0, (sum, p) -> sum += p.getDay(), (sum1, sum2) -> sum1 + sum2); System.out.println("DaySize=" + daySum);
      
      





この変形では、reduceは3つの値を取ります。1つ目は識別子、2つ目はバッテリー、3つ目は実際には「マージ」です。 他にもいくつかのオプションがあります。


この記事ではメソッドのごく一部しか説明していませんが、おそらく多くの関心を集め、新しいプロジェクトに登場するでしょう。 ラムダはともに、簡潔で高速に実行されるコードを作成するための優れたツールになります。 皆さん、頑張ってください。



All Articles