ディレクトリ
ストリーム、操作の途中が行われていない終了方法4.1.3を呼び出さないでください。
1.ストリームストリームの概要と思いました
ストリームフローアイデアはストリームフローはデータ構造ではない、工場フロア「生産ライン」に似ている、データが保存されていませんが、データ処理。ストリームは、生成物への原料ように複数のステップによって、組立ライン上で、パイプラインの段階として見ることができます。
ストリームの流れは、私たちは、このようなフィルタリング、スライシング、マッピング、検索、デエンファシス、統計情報、試合やプロトコルなどなど、多くの複雑な操作を、すぐに達成できるようになります。
注意:IOストリーム流れとは関係がありません。
2.知人ストリーム
ストリームは、8 Javaでの重合の多くの新機能の一つの動作を統合収集ツール複雑な操作、上の関数型プログラミングモードである開発者がより簡単にラムダ式を使用して、より容易に達成することができますトラバーサル、フィルタと共通のコンピューティングのコレクションを検索します。
オンデマンドで見てみましょうが、リストにリスト<Oject>セット内の一定の要件を満たしており、変換されたオブジェクトを見つけるために、<文字列>コレクション
JDK1.8前の練習は、次のとおりです。
private static List<String> getDishNameByList(List<Dish> dishs){
List<Dish> list = new ArrayList<>();
for(Dish d : dishs){
if(d.getCalories() < 400){
list.add(d);
}
}
Collections.sort(list,(dish1,dish2) -> Integer.compare(dish1.getCalories(),dish2.getCalories()));
List<String> names = new ArrayList<>();
for(Dish d : list){
names.add(d.getName());
}
return names;
}
ストリームのアプローチを使用します。
private static List<String> getDishNameByStream(List<Dish> dishs){
List<String> collect = dishs.stream().filter(d -> d.getCalories() < 400)
.sorted(Comparator.comparing(Dish::getCalories)).map(Dish::getName)
.collect(toList());
return collect;
}
3.取得する二つの方法ストリームのストリーム
取得ストリームコレクション3.1
コレクションのデフォルトのインターフェースの方法があります:デフォルトのストリーム<E>ストリーム()
定義では、すべてのインターフェイスは、たとえば、Collectionインタフェースは、ストリームのメソッドを持って知ることができます。
public class StreamDemo1 {
public static void main(String[] args) {
List list = new ArrayList();
Stream stream = list.stream();
Set set = new HashSet();
Stream stream1 = set.stream();
Map map = new HashMap();
Stream stream2 = map.keySet().stream();
Stream stream3 = map.values().stream();
Stream stream4 = map.entrySet().stream();
}
}
注:地図コレクションインタフェースは、そこには、ストリームクラスMap実装方法はありませんが、取得キーマップとセット値の例は、コレクションサブクラスストリーム方式を使用することができます設定され、サブインターフェースに属していません。
静的取得ストリームの方法により3.2ストリーム
static <T> Stream<T> of(T... values)
可変パラメータの種類を受け入れるの性質を知ることができ、可変のパラメータは、例えば、配列パラメータを受け入れることができ、言うことです配列は、次のとおりです。
public static void main(String[] args) {
Stream<String> stream = Stream.of("aa", "bb", "cc");
Integer[] arrar = {1, 2, 2, 3, 4, 5};
Stream<Integer> objectStream = Stream.of(arrar);
}
注:基本データ型の配列は、このように流動例で使用することができません。
int[] arr = {1, 2, 2, 3, 4, 5};
Stream<int[]> stream1 = Stream.of(arr);
ストリームを流動の方法を用いて上記int型の配列については、配列内の要素の動作なしに動作として見られるように全体のint []オブジェクトがある場合、INTに汎用INT []コンパイラはエラーになります。
4.一般的な方法でストリームのストリーム
ストリームの流れオペレーティングモデルは、非常に豊富で便利なAPIの多くを提供し、大きく二つに分けること
この方法の1)終了:戻り値の型は、もはや流れでは、もはやサポートチェーンの呼び出しではありません
2)非端子法:戻り型が連鎖コールをサポートするために、依然としてストリームである(メソッドの最後を除いて、残りは非終了方法です)
以下は、一般的に使用されるいくつかの簡単な方法は、次のとおりです。
メソッド名 | メソッドの役割 | 戻り値の型 | メソッドの種 |
カウント | 統計の数 | 長いです | 終了 |
forEachの | 1つのプロセスによるワン | 空隙 | 終了 |
フィルタ | 濾過 | ストリーム | ステッチング機能 |
限定 | 最初の数へのアクセス | ストリーム | ステッチング機能 |
スキップ | いくつかの前をスキップ | ストリーム | ステッチング機能 |
地図 | マッピング | ストリーム | ステッチング機能 |
連結 | 組み合わせ | ストリーム | ステッチング機能 |
ノート4.1ストリームのストリーム
4.1.1ストリームは一度だけこれを行うことができます
例えば:
Stream<String> stream = Stream.of("aa", "bb", "cc");
stream.count();
stream.count();
この方法は、カウントが間違って行くことはありません一度だけ呼び出された場合は、上記の2回呼び出した場合、ストリームフローオブジェクトについては、それは間違った情報を与えられます、次のとおりです。
4.1.2ストリーム方式新しいストリームを返します。
たとえば、次のように偽の戻り値
Stream<String> stream = Stream.of("aa", "bb", "cc");
Stream<String> limit = stream.limit(1);
System.out.println(stream == limit);
ストリーム、操作の途中が行われていない終了方法4.1.3を呼び出さないでください。
例えば:
public static void main(String[] args) {
Stream<String> stream = Stream.of("aa", "bb", "cc");
stream.filter((s) -> {
System.out.println(s);
return true;
});
}
私たちは、フィルタストリームのステッチ関数を呼び出すと、print文が実行されることはありません、print文を実行するためにendメソッドを呼び出す必要がある、など:
public static void main(String[] args) {
Stream<String> stream = Stream.of("aa", "bb", "cc");
stream.filter((s) -> {
System.out.println(s);
return true;
}).count();
}
4.2のforeach方法
foreachメソッドデータ・ストリームをトラバースするための方法が定義されています
void forEach(Consumer<? super T> var1);
该方法接收一个Consumer接口函数,会将每一个元素交给该函数进行处理。
例如:
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
Collections.addAll(list,"a","b","c","d","e","f");
list.stream().forEach(s->{
System.out.println(s);
});
// 上面的Lambda可以改成下面的方法引用的形式
list.stream().forEach(System.out::println);
}
同时我们也可以使用另一个集合去接收这个集合中的元素
List l = new ArrayList();
list.stream().forEach(l::add);
注意:对于foreach方法,可以不使用stream转换,例如;
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
Collections.addAll(list,"a","b","c","d","e","f");
list.forEach(s->{
System.out.println(s);
});
// 上面的Lambda可以改成下面的方法引用的形式
list.forEach(System.out::println);
}
4.3 count方法
Stream流提供count方法来统计其中的元素个数,方法定义为:long count(),该方法返回一个long值代表元素个数,
例如:
long count = list.stream().count();
4.4 filter方法
filter用于过滤数据,返回符合条件的数据,在开发中,我们可以通过filter将一个流转换成另一个子集流,方法声明:
Stream<T> filter(Predicate<? super T> var1);
该接口接收一个Predicate函数式接口参数(可以是一个Lambda或方法引用)作为筛选条件。
例如:
list.stream().filter( s -> s.indexOf("h") != -1 ).forEach(System.out::println);
注意:Lambda表达式,当只有一句话的return语句的时候,可以省略大括号省略return。
4.5 limit方法
limit方法可以对流进行截取,只取用前N个,方法定义:Stream<T> limit(long var1);
参数是long型,如果集合当前长度大于参数则进行截取,否则不进行操作。
例如:
list.stream().limit(4).forEach(System.out::println);
4.6 skip方法
如果希望跳过前几个元素,可以使用skip方法获取一个截取之后的新流,方法定义为:Stream<T> skip(long n),如果当流的当前长度大于n,则跳过前n个,否则将会得到一个长度为0的空流。
例如:
list.stream().skip(4).forEach(System.out::println);
4.7 map方法
如果需要将流的元素映射到另一个流中,可以使用map方法,方法定义为:
<R> Stream<R> map(Function<? super T, ? extends R> var1);
该接口需要一个Function函数式接口参数,可以将当前流中的T类型的数据转换为另一种R类型的流。
例如:map将一个String流转成了Integer流
Stream<String> strStream = list.stream();
Stream<Integer> stream = strStream.map(Integer::parseInt);
4.8 sorted方法
如果需要将数据排序,可以使用sorted方法,方法定义为
Stream<T> sorted(); // 自然顺序排序
Stream<T> sorted(Comparator<? super T> var1); // 自定义排序
例如:
public class StreamSorted {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
Collections.addAll(list,1,5,2,4,8,10);
list.stream().sorted() // 自然顺序排序
.sorted((i1,i2) -> i2-i1) // 降序排序
.forEach(System.out::println);
}
}
4.9 distinct方法
如果需要去除重复数据,可以使用distinct方法,方法定义:Stream<T> diatinct(),例如:
list.stream().distinct().forEach(System.out::println);
注意:对于自定义类型的数据,去重需要类对象重写hashCode与equals方法。
4.10 match方法
如果需要判断数据是否匹配指定的条件,可以使用match相关方法,方法定义
boolean anyMatch(Predicate<? super T> var1); // 匹配任意一个,只要有一个满足指定条件就可以
boolean allMatch(Predicate<? super T> var1); // 匹配所有元素,元素是否全部满足指定条件
boolean noneMatch(Predicate<? super T> var1); // 匹配所有元素,所有元素都不满足指定条件
例如:
package com.bjc.jdk8.stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class StreamMatch {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
Collections.addAll(list,1,5,2,4,8,10);
boolean b = list.stream().allMatch(i -> i > 0);
System.out.println(b);
boolean b1 = list.stream().anyMatch(i -> i > 5);
System.out.println(b1);
boolean b2 = list.stream().noneMatch(i -> i < 0);
System.out.println(b2);
}
}
返回结果均为true。
4.11 find方法
如果需要找到某些数据,可以使用find相关方法,方法定义:
Optional<T> findFirst();
Optional<T> findAny();
注意:这两个方法都是查找流中的第一个元素
例如:
package com.bjc.jdk8.stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class StreamFind {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
Collections.addAll(list,1,5,2,4,8,10);
Integer integer = list.stream().findFirst().get();
System.out.println(integer);
Integer integer1 = list.stream().findAny().get();
System.out.println(integer1);
}
}
输出结果都是1
4.12 获取最大最小值
如果需要获取最大值和最小值,可以使用max和min方法,方法定义:
Optional<T> min(Comparator<? super T> var1);
Optional<T> max(Comparator<? super T> var1);
例如:
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
Collections.addAll(list,1,5,2,4,8,10);
Integer integer = list.stream().max((o1,o2) -> o1 - o2).get();
System.out.println(integer);
Integer integer1 = list.stream().min((o1,o2) -> o1 - o2).get();
System.out.println(integer1);
}
4.13 reduce方法
如果需要将所有数据归纳得到一个数据,可以使用reduce方法,方法定义:
T reduce(T var1, BinaryOperator<T> var2);
第一个参数:默认值
第二个参数:数据处理逻辑,BinaryOperator继承自BiFunction,且BinaryOperator接口中无抽象的方法,所以,找父类的BiFunction的抽象方法
R apply(T var1, U var2);
例如:带默认值的reduce
package com.bjc.jdk8.stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
public class StreamReduce {
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, 3, 4, 5, 2, 7, 9);
Integer reduce = stream.reduce(0, (x, y) -> x + y);
System.out.println(reduce);
}
}
或者,不带默认值的reduce
package com.bjc.jdk8.stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class StreamReduce {
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, 3, 4, 5, 2, 7, 9);
Optional<Integer> reduce = stream.reduce((x, y)->x+y);
System.out.println(reduce.get());
}
}
4.14 Stream流的map与reduce组合使用
通过Stream流的map与reduce的组合使用可以大大的简化我们对集合的操作
例如:定义如下对象流
Stream<Person> stream = Stream.of(
new Person("张三",22),
new Person("李四",23),
new Person("王五",21),
new Person("赵六",26),
new Person("钱七",25)
);
1)求出所有的年龄之和
// Integer reduce = stream.map(p->p.getAge()).reduce(0, (x, y) -> x+y);
Integer reduce1 = stream.map(Person::getAge).reduce(0, (x, y) -> x + y);
System.out.println(reduce);
注意:因为Integer有一个sum方法可以求和,所以,上面的代码还可以改成如下形式:
Integer reduce1 = stream.map(Person::getAge).reduce(0, Integer::sum);
2)找出最大年龄
Optional<Integer> reduce = stream.map(Person::getAge).reduce(Integer::max);
Integer integer = reduce.get();
System.out.println(integer);
3)统计一个流中a出现的次数
例如:
Stream<String> stream1 = Stream.of(
"a","b","c","a","a","f","a","d"
);
Optional<Integer> option = stream1.map(str -> "a".equals(str) ? 1 : 0).reduce(Integer::sum);
Integer integer = option.get();
System.out.println(integer);
4.15 mapToInt方法
如果需要将Stream<Integer>中的Integer类型数据转换成int类型,可以使用mapToInt方法,方法定义为:
IntStream mapToInt(ToIntFunction<? super T> mapper);
我们为什么要将Integer流转成int了,这是因为Integer占用的内存比int多,在Stream流操作中会自动装箱和拆箱,经过mapToInt方法转换之后,就将一个Integer类型的stream转成了一个IntStream,那么这个IntStream流与Stream流有什么关系了?如下图所示,两者有一个父接口Basestream,只是IntStream内部操作的是int数据,可以节省内存,减少自动拆箱装箱。
例如:
public class StreamMapToInt {
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
IntStream intStream = stream.mapToInt(Integer::intValue);
intStream.forEach(System.out::println);
}
}
4.16 静态方法concat方法
如果有两个流,希望合并成为一个流,那么可以使用Stream接口的静态方法concat,方法定义:
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
Objects.requireNonNull(a);
Objects.requireNonNull(b);
@SuppressWarnings("unchecked")
Spliterator<T> split = new Streams.ConcatSpliterator.OfRef<>(
(Spliterator<T>) a.spliterator(), (Spliterator<T>) b.spliterator());
Stream<T> stream = StreamSupport.stream(split, a.isParallel() || b.isParallel());
return stream.onClose(Streams.composedClose(a, b));
}
例如:
public class StreamConcat {
public static void main(String[] args) {
Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六");
Stream<String> stream1 = Stream.of("钱七", "朱八", "宫九");
Stream<String> concat = Stream.concat(stream, stream1);
concat.forEach(System.out::println);
}
}
注意:当使用concat合并流之后,合并之前的流不能使用了,否则会报如下错