[モダンジャワ動作]chp 5利用フロー(1)

11955 ワード

だから、どのように流れを利用しますか?この章では、ストリームAPIをサポートする様々な演算について説明します.Java 8と9に追加された様々な演算を表示します.
ストリームAPIがサポートする演算は、フィルタリング、スライド、マッピング、検索、マッチング、再生など、様々なデータ処理クエリを表すことができる.

00フィルタ


00節では、フロー要素を選択する方法、すなわち、プリセット要素をフィルタする方法、および一意の要素のみをフィルタする方法について説明します.

(1)プリセットによるフィルタリング


ストリームインタフェースはfilterメソッドをサポートします.filterメソッドはpredicate(ブール関数を返す)をパラメータとして受け入れ、predicateと一致するすべての要素を含むストリームを返します.
List<Dish> vegetarianMenu = menu.stream()
								.filter(Dish::isVegetarian)
                                .collect(toList());

(2)一意要素のフィルタ


ストリームはidstinctメソッドもサポートし、一意の要素からなるストリームを返します.(オブジェクトのhashCode,equalsのみによって決定されるかどうか.)たとえば、次のコードはリスト内のすべての偶数を選択し、重複をフィルタします.
List<Dish> vegetarianMenu = menu.stream()
								.filter(i -> i % 2 ==0)
                      			.disticnt()                         
                                .forEach(System.out::printtln);

01スリップ


01節では、ストリーム内の要素を選択またはスキップする方法について説明します.これらのタスクは、プリセットの方法、ストリームの最初の要素を無視する方法、ストリームを特定のサイズに縮小する方法など、さまざまな方法で効率的に実行できます.

(1)Predicateを用いたスライド(takeWhile,dropWhile)


リスト要素から300以下のカロリーを選ぶと?
上で使用したfilter()を使用して、filter(dish->dish.getCalories()<300)を指定します.しかし、すでに並べ替えられたリストであれば、300以上のカロリーが出ている要素から繰り返しを止めることができます.この場合takeWhileを使用します.
List slicedMenu = menu.stream()
	.takeWhile(dish -> dish.getCalories() < 300)
	.collect(toList());
上のtakeWhileとは逆のdropWhileもあります.dropWhileは、Predicatが最初にエラーが発生するまで、検出された要素を破棄します.

(2)ストリーム収縮(limit)、スキップ要素(skip)


与えられた値n個の要素を有するストリームはlimit(n)によって返される.
skip(n)は、前のn要素と後のn要素のみを含むストリームを返す.
Limitとskipの結果は相補的な演算です

02マッピング


特定のオブジェクトから特定のデータを選択する操作
ex.Dishオブジェクトを要素とするストリーム――マッピング*Dishオブジェクトのカロリー値を要素とするストリーム

(1)ストリーム内の各要素に関数を適用する


mapメソッドは、提供された関数を各要素に適用することによって、得られた結果を新しい要素にマッピングする関数を引数として受け入れます.
mapメソッドの出力ストリームは、パラメータとして提供される関数の戻りタイプTに対するStreamである.

(2)流平面化


状況:["Hello", "World"]リストには、文字列を構成する一意のアルファベットのリストが含まれています.["H","e", "l", "o", "W", "r", "d"]の返金を受け取りたいです.
誤った方法mapメソッドを使用して単語を単一文字にマッピングしdistinctを掛けた場合...?
words.stream().map(word -> word.split(""))   //단일문자 매핑
              .distinct().collect(toList()); //distinct
ここでの問題はmapメソッドが返すタイプがStreamではなくStream誤った方法地図とArraysりようりゅう
Arrays.stream()メソッドはString配列をパラメータとして受け入れ,それをStreamにする.
ただし、mapメソッドで返されるストリームオブジェクトについては.map(Arrays::stream)メソッドを追加すると、String配列ごとに個別のストリームが作成され、最終的にリストに戻ります.
解決策.FlatMapを使用して単一ストリームを返す
エラーメソッド2の問題は.map(Arrays.stream)から返されるオブジェクトはストリームではなく、String配列ごとにストリームを生成します.(.distict()メソッドは、各要素がストリーム中にあるため、あまり意味がありません.)
FlatMapを使用すると、各要素で生成されたストリームを1つのストリームに平面化できます.
つまり、戻されたStream Streamオブジェクト上にあります.distinct()をフィルタすると、目的の一意のアルファベット["H"、"e"、"l"、"o"、"W"、"r"、"d]]を返すことができます.

03検索と照合


(1)Predicateを使用して要素をチェックする


上記の3つの方法はbooleanを返し、javaの&&、|)のようなストリームの短いパケット技術を使用する.
短いループは、前条件式の結果&および|に基づいて後条件式を実行するかどうかを決定する論理演算子です.
//- allMatch

  //스트림의 모든 요소가 주어진 Predicate과 일치하는지 여부 반환

boolean isHealthy = menu.stream().allMatch(d -> d.getCalories() < 1000);

//- anyMatch

  //스트림의 요소 중에서 Predicate과 일치하는 경우가 적어도 하나라도 있는지 여부 반환

// - noneMatch

  //allMatch와 반대되는 연산

(2)検索要素


findAny
他のストリームに関連付けて使用し、条件を満たすストリーム要素がある場合は戻します.以下の例で用いるOptionalクラスはjava 8から提供されるクラスでありnull処理などを容易に行うことができる.Optional dish = menu.stream().filter(Dish::isVegetarian).findAny();findFirst
ストリームはソートされ、リストされています.論理的なアイテムの順序があるかもしれません.ストリーム内の最初の要素を検索します.

04再生産


これまで、本ストリームの最終演算方法(allMatch、forEach、findAny)はboolean、void、Optionalオブジェクトを返してきた.再生演算には、すべてのストリーム要素を処理し、値としてエクスポートする必要があります.
ex.メニュー上の全カロリーの合計

(1)要素の和

int sum = numbers.stream().reduce(0, (a,b) -> a + b);
上記の例では、reduceメソッドを使用して、ストリーム内のすべての要素の和を求めます.この方法には2つの引数があり,1つ目は初期値,2つ目は2つの要素を組み合わせて新しい値を作成するBinaryOperatorである.
JAva 8は、2つの数字をIntergerクラスに加算する静的および方法を提供するので、Integer::Ramda式ではなくsumをスキップすることができる.
reduceメソッドは初期値パラメータを受け入れない場合があるが,インスタンスはオプションで囲まれたオブジェクトを返すことでNPEなどの問題を回避する.

(2)最大値と最小値


reduceメソッドのパラメータでは、ストリーム内の2つの要素が最大値と最小値を返すramのみを提供する場合、要素全体から最大値と最小値を取得できます.(ラムダ式を消費流中のすべての元素まで繰り返します)
  Optional<Integer> max = numbers.stream().reduce(Integer::max);

(3)reduceメソッドの利点と並行


foreach文を使用する外部反復、例えばsum+=i;このように和を求めるのは並列処理が難しい.スレッドを作成した後、タスクを並列処理に分割する場合は、スレッド間でsumを共有する必要があります.
reduceは内部反復を抽象化し,内部実装でreduceメソッドを並列に実行できる.
ParallelStream()を使用すると、すべてのストリーム要素を並列に処理できますが、リソースが失効する可能性があるため、使用に適しているかどうかを確認する必要があります.(後述)

(4)フロー計算における無状態概念


map、filterなどのメソッドでは、各要素を処理し、結果を出力ストリームに送信します.すなわち、内部参照や管理の内部状態の演算(無状態操作)を備えていない.
reduce,sum,maxなどの演算には計算結果を蓄積する内部状態が必要である.しかし,いくら要素数が多くても,これまでの総和のように参照すべき内部状態の大きさは限られている.
最も主要な問題はソート、distictなどの演算であり、これらの演算はストリーム内のすべての要素をバッファに追加する必要があるため、ストリームのサイズが大きい場合、負荷が発生する可能性があります.この演算を内部状態を有する演算と呼ぶ.