宣言型データ収集プロセスの流れ特性は、許可コードはシンプルで読みやすくなるので、新機能のJava8主にラムダ式と流れ、ストリームやラムダ式は、と組み合わせて使用する場合
コードストリームを簡素化する方法を増幅するストローク、
需要があれば、データベースクエリの必要性は、料理の過程であることを:
- スクリーニング未満400カロリー料理
- 料理は、ソートしたうちのスクリーニング
- 注文後の名前の料理を取得します。
料理:Dish.java
public class Dish {
private String name;
private boolean vegetarian;
private int calories;
private Type type;
// getter and setter
}
复制代码
実施前Java8
private List<String> beforeJava7(List<Dish> dishList) {
List<Dish> lowCaloricDishes = new ArrayList<>();
//1.筛选出卡路里小于400的菜肴
for (Dish dish : dishList) {
if (dish.getCalories() < 400) {
lowCaloricDishes.add(dish);
}
}
//2.对筛选出的菜肴进行排序
Collections.sort(lowCaloricDishes, new Comparator<Dish>() {
@Override
public int compare(Dish o1, Dish o2) {
return Integer.compare(o1.getCalories(), o2.getCalories());
}
});
//3.获取排序后菜肴的名字
List<String> lowCaloricDishesName = new ArrayList<>();
for (Dish d : lowCaloricDishes) {
lowCaloricDishesName.add(d.getName());
}
return lowCaloricDishesName;
}
复制代码
Java8の実施後
private List<String> afterJava8(List<Dish> dishList) {
return dishList.stream()
.filter(d -> d.getCalories() < 400) //筛选出卡路里小于400的菜肴
.sorted(comparing(Dish::getCalories)) //根据卡路里进行排序
.map(Dish::getName) //提取菜肴名称
.collect(Collectors.toList()); //转换为List
}
复制代码
すべて1で、その足をドラッグしない、書くため、元の必要性24
を達成するために機能コードは今だけです5
完成するライン
- データベースクエリの料理は料理の種類に応じて分類され、それが返す
Map<Type, List<Dish>>
結果を
これはjdk8前頭皮に間違いだった場合
実施前Java8
private static Map<Type, List<Dish>> beforeJdk8(List<Dish> dishList) {
Map<Type, List<Dish>> result = new HashMap<>();
for (Dish dish : dishList) {
//不存在则初始化
if (result.get(dish.getType())==null) {
List<Dish> dishes = new ArrayList<>();
dishes.add(dish);
result.put(dish.getType(), dishes);
} else {
//存在则追加
result.get(dish.getType()).add(dish);
}
}
return result;
}
复制代码
幸い、jdk8ストリームがあり、もはや処理要件の複雑なセットを心配する必要はありません
実施後Java8
private static Map<Type, List<Dish>> afterJdk8(List<Dish> dishList) {
return dishList.stream().collect(groupingBy(Dish::getType));
}
复制代码
、需要を解決するためのコードの行で叫んで助けることができなかったStream API
牛がバーの流れを見るために力を与えられ、次の詳細な流れになります
フローとは何ですか
ソース・ストリームによって生成された要素の配列が支持体からのデータ処理操作であり、ソースは、アレイ、ファイル、関数のセットであることができます。フローは、要素のコレクションではありません、それはデータのデータ構造ではありません保存されていない、その主な目的は、計算することです。
ストリームを生成する方法
フロー生成5つの主要な方法があります
- セットを生成することにより、最も一般的なアプリケーションの1
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = integerList.stream();
复制代码
設定されたstream
ストリームを生成する方法
- 配列によって生成されました
int[] intArr = new int[]{1, 2, 3, 4, 5}; IntStream stream = Arrays.stream(intArr); 复制代码
Arrays.stream
フロー生成方法、及びプロセスのストリームが生成された値のストリームである[すなわちIntStream
]の代わりにStream<Integer>
。パフォーマンスを向上させるために、梱包を開梱の数値フロー計算処理を使用しないようにそれを追加します。Stream API
提供mapToInt
、mapToDouble
、mapToLong
3つの方法が、すなわち、オブジェクトストリームは、[ Stream<T>
提供しつつ]、値の対応するストリームに変換されるboxed
オブジェクトに数値流れの方法を
- 値を生成します
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5); 复制代码
ストリームを生成する方法、によって方法空気の流れを生成することができますStream
of
Stream
empty
- ファイルの生成により、
Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset()) 复制代码
Files.line
フロー法を得、得られたストリームをファイルにライン毎に与えられます
- 関数発生器によって提供される
iterate
とgenerate
2つの静的メソッドは、関数から生成されたストリーム- イテレータ
Stream<Integer> stream = Stream.iterate(0, n -> n + 2).limit(5); 复制代码
iterate
方法は、第2の動作の関数として、2つのパラメータ最初の初期値をとるiterator
ストリームが無限に流れるされて生成されたlimit
トランケートされた対流方法もわずか5発生します、- 発生器
Stream<Double> stream = Stream.generate(Math::random).limit(5); 复制代码
generate
この方法は、パラメータの型がメソッドであり、一つのパラメータをとりSupplier<T>
流量値を提供することによって。generate
ストリームの流れが無限に発生し、従ってによってれるlimit
実施対流切り捨て
操作タイプの流れ
操作種別は、2つの主要な流れに分割されています
- ストリーム続く中間演算は、ゼロ以上の中間の動作であってもよいです。その主な目的は、データマッピング/フィルタリングのいくつかの学位を作り、流れを開くことですし、次の操作を使用して、新しいストリームを返します。このような動作は、実際の必要性は、以下の共通の中間体の動作が導入されなければならない、端末トラバース操作されるまで待機するだけこのような方法を呼び出し、ストリームの実際の開始を横断しない、不活性である
filter
、map
等 - 端末操作ストリームは、操作が行われた場合、ストリームはストリームしたがってもう一度で生成されたソース・データのストリームを横断する必要性を横断することができ、それはもはや動作することができない、閉鎖された、唯一つの端末の動作を有しています。行っターミナルの操作は、ストリームの本当の始まりを横断します。すぐ下に記載されるように
count
、collect
等
ストリーミングを使用します
導入された端末操作と中間操作を使用してストリームに
中級操作
フィルタースクリーニング
List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5);
integerList.stream().filter(i -> i > 3).forEach(System.out::println);
复制代码
使用してfilter
条件付きのスクリーニング方法を、filter
メソッドパラメータが条件であります
個別の削除重複要素
List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5);
integerList.stream().distinct().forEach(System.out::println);
复制代码
distinct
方法迅速な除去繰り返しエレメント
指定された制限ストリームの数を返します。
List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5);
integerList.stream().limit(3).forEach(System.out::println);
复制代码
limit
リターンフロー方式の指定された数は、limit
パラメータ値がでなければならない>=0
、それ以外の場合は、例外がスローされます
スキップストリーム要素をスキップ
List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5);
integerList.stream().skip(2).forEach(System.out::println);
复制代码
skip
エレメンタリストリームスキッピングの方法であって、上記の例の前に2つの要素をスキップし、印刷結果2,3,4,5
、skip
パラメータ値が必要があり>=0
、そうでない場合は、例外がスローされます
地図フローマッピング
いわゆるフローマッピングは、他の受光素子に要素をマッピングすることです
List<String> stringList = Arrays.asList("Java 8", "Lambdas", "In", "Action");
stringList.stream().map(String::length).forEach(System.out::println);
复制代码
map
完全なマッピング方法、例えば完了String -> Integer
マッピングの、上記の実施例による前map
処理を完了するためにDish->String
マッピングを
flatMapストリーム変換
ストリームの各値は、別のストリームに変換されます。
List<String> stringList = Arrays.asList("Hello", "World");
List<Stream<String>> str = stringList.stream()
.map(world -> world.split(" "))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList());
复制代码
map(world -> world.split(" "))
戻り値Stream<String[]>
は、我々は結果が得られると考えるStream<String>
ことができ、flatMap
メソッド完了Stream<String[]> ->Stream<String>
変換を
要素が一致します
これは3つの方法の一致を提供します
- allMatchすべての一致
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); if (integerList.stream().allMatch(i -> i > 3)) { System.out.println("值都大于3"); } 复制代码
することによりallMatch
達成する方法
- anyMatch 1試合
に相当List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); if (integerList.stream().anyMatch(i -> i > 3)) { System.out.println("存在大于3的值"); } 复制代码
for (Integer i : integerList) { if (i > 3) { System.out.println("存在大于3的值"); break; } } 复制代码
図3は、プリントの現在値よりも大きいjava8
ことによりanyMatch
、この方法を達成します
- noneMatchすべての不一致
することによりList<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); if (integerList.stream().noneMatch(i -> i > 3)) { System.out.println("值都小于3"); } 复制代码
noneMatch
達成する方法
ターミナル事業
統計フロー内の要素の数
- countで
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); Long result = integerList.stream().count(); 复制代码
使用することによりcount
、フロー方式の要素数の統計を
- カウントすることにより
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); Long result = integerList.stream().collect(counting()); 复制代码
素子数の統計の最終的な方法とcollect
組み合わせて使用される場合に特に有用です
求めます
それは見つけるための2つの方法が用意されてい
-
まず、検索関数は、FindFirst
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); System.out.println(integerList.stream().filter(i -> i > 3).findFirst()); 复制代码
よる
findFirst
3とプリントよりも大きい最初の要素への参照方法 -
ランダムfindAnyを探します
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); System.out.println(integerList.stream().filter(i -> i > 3).findAny()); 复制代码
findAny
ため、内部最適化三およびプリント、より大きな要素の1つにルックアップ方式と、3つ以上の最初の要素が大きい満たすことが見出された場合には、方法及び結果終了したfindFirst
結果と同じように。それは提供しfindAny
、並列ストリームのより有効に活用するためのメソッドをfindFirst
[この記事では、並行して並列ストリームを紹介しません]の方法は、より限定されました
結合ストリーム要素を減らします
私たちは一連の値を合計したものと
-
jdk8前
int sum = 0; for (int i : integerList) { sum += i; } 复制代码
-
削減jdk8によって処理された後、
int sum = integerList.stream().reduce(0, (a, b) -> (a + b)); 复制代码
行が完了することができ、この方法は、速記参照として使用してもよいです。
int sum = integerList.stream().reduce(0, Integer::sum); 复制代码
reduce
それは、2つのパラメータ、ここでは初期値受け入れ0
、BinaryOperator<T> accumulator
二つの要素には、に加えて、新たな価値を生み出すために結合するreduce
方法と値の初期化メソッドをオーバーライドしません
最小および最大流量を求めます
- 最小の最小値/最大値の最大値を取得することにより
Optional<Integer> min = menu.stream().map(Dish::getCalories).min(Integer::compareTo); Optional<Integer> max = menu.stream().map(Dish::getCalories).max(Integer::compareTo); 复制代码
min
、最小流量を求めるmax
引数で、最大流量を求めますComparator<? super T> comparator
- 最小minBy / maxByの最大値を取得することにより
Optional<Integer> min = menu.stream().map(Dish::getCalories).collect(minBy(Integer::compareTo)); Optional<Integer> max = menu.stream().map(Dish::getCalories).collect(maxBy(Integer::compareTo)); 复制代码
minBy
、最小流量を求めるmaxBy
引数で、最大流量を求めますComparator<? super T> comparator
- 最小値と最大取得することにより削減
Optional<Integer> min = menu.stream().map(Dish::getCalories).reduce(Integer::min); Optional<Integer> max = menu.stream().map(Dish::getCalories).reduce(Integer::max); 复制代码
理解することは簡単で、最小の最大値を取得するための最後の方法を好みます
summingIntを合計することによって、
int sum = menu.stream().collect(summingInt(Dish::getCalories));
复制代码
に相当することによりreduce
:
int sum2 = menu.stream().map(Dish::getCalories).reduce(0, Integer::sum);
复制代码
最初のアプローチを使用することを好む、reduce
合計はそれが比較より宣言的である場合、データ・タイプdouble
、 long
次いでスルーsummingDouble
、summingLong
加算方法
averagingIntを平均化することにより
double average = menu.stream().collect(averagingInt(Dish::getCalories));
复制代码
データを入力するとdouble
、 long
次に介してaveragingDouble
、averagingLong
平均化のための方法
同時にsummarizingInt合計、平均、最大値、最小値を取得することにより
IntSummaryStatistics intSummaryStatistics = menu.stream().collect(summarizingInt(Dish::getCalories));
double average = intSummaryStatistics.getAverage(); //获取平均值
int min = intSummaryStatistics.getMin(); //获取最小值
int max = intSummaryStatistics.getMax(); //获取最大值
long sum = intSummaryStatistics.getSum(); //获取总和
复制代码
データ型の場合double
、long
その後を通じてsummarizingDouble
、summarizingLong
方法
groupingByによってグループ化された高度な
Map<Type, List<Dish>> result = dishList.stream().collect(groupingBy(Dish::getType));
复制代码
中にcollect
入ってくるプロセスgroupingBy
群、前記groupingBy
プロセスパラメータは、分類の関数です。また、入れ子にすることができgroupingBy
、マルチクラス分類器を
Map<Type, List<Dish>> result = menu.stream().collect(groupingBy(Dish::getType,
groupingBy(dish -> {
if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT;
})));
复制代码
partitioningByによって高度なパーティション
パーティションは、trueとfalseに基づいて分類特殊なグループであり、その結果は、2つのグループにまで戻りました
Map<Boolean, List<Dish>> result = menu.stream().collect(partitioningBy(Dish :: isVegetarian))
复制代码
に相当
Map<Boolean, List<Dish>> result = menu.stream().collect(groupingBy(Dish :: isVegetarian))
复制代码
この例では、パーティション少し明白な例を変更する必要はありませんでしたでも、ゾーニングと分類、との違いが表示されないことがあります。
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
Map<Boolean, List<Integer>> result = integerList.stream().collect(partitioningBy(i -> i < 3));
复制代码
戻り値は、結合のブールタイプが残っているが、その分類は、範囲に従って分類され、範囲に応じて、ゾーニングの分類を処理するためのより適切な
要素を結合することによりスプライシングされたストリーム
String result = menu.stream().map(Dish::getName).collect(Collectors.joining(", "));
复制代码
ない場合、デフォルトによるmap
スプライシングのマッピング処理方法toString
メソッドによって返される文字列、要素パラメータの区切りを接合するための方法であって、結果の文字列が文字列である場合に可読性が強くない指定しません
概要
使用するとStream API
、コードの可読性を向上させながら、コードを簡略化することができ、かつ迅速にプロジェクトに使い切ります。学ばなかった理由Stream API
の前には、内のアプリケーションの多くで私を書いた人たちはLambda
、Stream API
彼の足を飛ぶことを望んでいました。私は彼を愛するかもしれないと思う[喜喜]。時間の宣言型と命令型プログラミングのミックスを使用しないように注意し、同時に、ブラシの数日前には、segment
ブラシに:
imango
兄はそれが正しい、と
宣言型プログラミングのフックを使用しないでください文法は命令型プログラミングを乾燥します