JAva 8ストリーム(Stream API)使用の詳細:フィルタ、スライス、マッピング、検索、マッチング、集約などのストリーム操作

6869 ワード

前編では集合操作の痛み点を紹介し,集合操作のこれらの痛み点がjava 8ストリームAPIの前ではほとんど問題ではないことを発見し,その後ストリームの定義を引き出し,ストリーム操作のタイプ,特徴,およびストリームを使用する基本手順を紹介し,この編ではStream Apiにおける各種ストリーム操作およびいくつかの特殊なストリームの使用について逐一紹介する.
述語でフィルタする
フィルタリングについては,このシリーズの前の文章で何度も登場しているが,ここでは再び以下のように列挙し,完全性を求めた.ベジタリアンメニューを次のコードでフィルタします.
 
  • List vegetarianMenu = menu.stream()
  • .filter(Dish::isVegetarian)//
  • .collect(toList());

  • フィルタの重量除去:distinct()関数
    重量除去とは、フィルタ結果の重複項目を除去し、fiterの後にdistinct()を呼び出すだけでよい.
     
  • List numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
  • numbers.stream().filter(i -> i % 2 == 0).distinct().forEach(System.out::println);

  • ストリームの短縮:limit関数
    ショートストリームとは、300カロリー以上のカロリーを取り出した最初の3つの料理など、ストリームからデータの一部を切り取ることです.
     
  • List dishes = menu.stream()
  • .filter(d -> d.getCalories() > 300)
  • .limit(3)//
  • .collect(toList());

  • スキップ要素:skip(int)関数
    スキップ要素とは、ストリームに指定された数の要素をスキップし、残りを操作または取り出します.次のコードのように、300カロリー以上の最初の3つの料理をスキップします.
     
  • List dishes = menu.stream()
  • .filter(d -> d.getCalories() > 300)
  • .skip(3)// 3
  • .collect(toList());

  • メニューフローのカロリーが300カロリーより大きい料理が3つ未満の場合、上記のコードは空のListを返します.
    マッピング:map
    ストリームのマッピングとは、対流の各要素に指定された関数を適用し、必要な新しい要素にマッピングすることです.メニューからメニュー名のリストをマップした場合、コードは次のとおりです.
     
  • List dishNames = menu.stream()
  • .map(Dish::getName)//map
  • .collect(toList());

  • メニューストリームStreamは、mapマッピング操作Dish::getNameを経て、文字ストリームStream、すなわち料理名ストリームに変換される.
    ストリームのフラット化:flatMap
    フローの平坦化操作flatMapは、一般的には複数のフローを1つのフローに統合することである.もし私たちが与えられた単語のリスト[「Hello」,「World]]を重いアルファベットのリスト[「H」,「e」,「l」,「o」,「W」,「r」,「d]]に分割する必要がある場合、どうすればいいですか.
    試行1:mapとdistinctの使用
     
  • // Stream
  • words.stream()
  • // Stream
  • .map(word -> word.split(""))
  • // , String[]
  • .distinct()
  • // List
  • .collect(toList());

  • 試行1失敗宣言!
    試行2:mapとArraysを使用します.stream()
     
  • // Stream
  • words.stream()
  • // Stream
  • .map(word -> word.split(""))
  • //Arrays::stream Stream
  • .map(Arrays::stream)
  • .distinct()
  • // List>
  • .collect(toList());

  • 試行2失敗宣言!
    試行3:flatMapの使用
     
  • List uniqueCharacters =
  • // Stream
  • words.stream()
  • // Stream
  • .map(w -> w.split(""))
  • //flatMap Stream Stream
  • .flatMap(Arrays::stream)
  • //
  • .distinct()
  • // List
  • .collect(Collectors.toList());

  • 试み3成功を告げる!
    anyMatch:少なくとも1つの要素を一致させる
    メニューにベジタリアンが存在するかどうかを検索し、ベジタリアンに一致すると終了しtrueに戻ります.
     
  • if(menu.stream().anyMatch(Dish::isVegetarian)){
  • System.out.println(" !");
  • }

  • allMatch:すべての要素に一致
    メニューのすべての料理が健康食品であるかどうかを検査します(熱量が1000未満であれば健康です):
     
  • if(menu.stream().allMatch(d -> d.getCalories() < 1000)){
  • System.out.println(" , 1000");
  • }

  • NoneMatch:すべての要素が一致しません
     
  • if(menu.stream().noneMatch(d -> d.getCalories() >= 1000)){
  • System.out.println(" , 1000");
  • }

  • 任意の要素を検索:findAny
    たとえば、メニュー内のベジタリアン料理を見つけます.
     
  • Optional dish = menu.stream().filter(Dish::isVegetarian).findAny();

  • findAnyは、現在のストリームのいずれかの要素を返します.java.util.Optionalは、Tを包む容器類である、上記のコードのOptionalのように、Dishが装着された容器を理解することができ、このDishは空とすることができ、optionalを通過することができる.get()メソッドはこのコンテナに入っているものを取得し,このシリーズの後の記事ではOptionalクラスの使い方を詳しく紹介する.
    最初の要素の検索:findFirst()
    最初の平方エネルギーが3で割り切れる数を見つけます.
     
  • List someNumbers = Arrays.asList(1, 2, 3, 4, 5);
  • Optional firstSquareDivisibleByThree =
  • someNumbers.stream()
  • .map(x -> x * x)
  • .filter(x -> x % 3 == 0)
  • .findFirst(); // 9

  • findAnyに比べて、findFirstは並列により多くの制限があり、どの要素を見つけるか気にしない場合はfindAnyを推奨します.
    集計操作:reduceを使用して和を求める
    帰約操作とは、ストリーム内のすべての要素を繰り返し組み合わせて値を得ることです.たとえば、ストリーム内の要素の合計:int sum = numbers.stream().reduce(0, (a, b) -> a + b);どうして繰り返して組み合わせるのですか?加算帰約動作では、指定された初期値0(reduceメソッドの最初のパラメータ)をストリームの最初の要素に加算し(reduceとして表現された2番目のパラメータBinaryOperatorであり、Lambda式(a,b)->a+bと伝達する)が中間値を得た後、ストリームのすべての要素が加算され、最終的な加算結果が得られるまでストリームの2番目の要素に加算する.
    reduceは1つのパラメータのリロード関数のみを受け入れます
     
  • Optional sum = numbers.stream().reduce((a, b) -> (a + b));

  • 違いは戻り値がOptionalになったことです.
    帰約操作:reduceを利用して最大と最小値を求める
     
  • //
  • Optional max = numbers.stream().reduce(Integer::max);
  • //
  • Optional min = numbers.stream().reduce(Integer::min);

  • 注意:reduce操作で最も重要なのは、ストリーム内の2つの要素を順次結果として新しい値を生成するためにLambda式またはメソッド参照を指定することです.