java8 Stream 史上最全總結
溫馨提醒:在電腦上看更方便
(一)stream的特點
一、 流操作都支持 lambda 表達式作爲參數 ,函數式編程,充分利用了pipeline 思想
二、無修改 ,無儲存
對原始數據無修改,對流和流的中間結果無儲存
三 、 惰性執行
四、可以併發執行 , paralleStream
五、 默認只消費一次
1) 巧妙避免代碼重複的方式 Supplier
-
Supplier<Stream<String>> streamSupplier = () -> Stream.of("1", "2").filter(t -> t.equals("1"));
-
final Optional<String> any = streamSupplier.get().findAny();//1
-
final Optional<String> first = streamSupplier.get().findFirst();//2
六、Map 不支持 stream 流
(二)函數接口簡介
1)一元函數式接口
接口 | 參數 | 返回類型 | 描述 |
---|---|---|---|
Predicate | T | boolean | 斷言型接口 |
Consumer | T | void | 消費型接口 |
Function | T | R | 函數式接口 |
Supplier | None | T | 供給型接口 |
2) 二元函數接口
接口 | 參數 | 返回類型 | 描述 |
---|---|---|---|
BiFunction | T, U | R | Function的變體 |
BiConsumer | T, U | void | Consumer的變體 |
BiPredicate | T, U | boolean | Predicate的變體 |
BiConsumer
-
final HashMap<Object, Object> objectObjectHashMap = Maps.newHashMap();
-
final BiConsumer biConsumer = (k, v) -> {
-
System.out.println(k);
-
System.out.println(v);
-
};
-
objectObjectHashMap.forEach(biConsumer);
BiPredicate
-
Path testPath = Paths.get("/Users/qiaozhy/data");
-
//finding files containing 'items' in name
-
final BiPredicate<Path, BasicFileAttributes> items = (path, basicFileAttributes) -> {
-
File file = path.toFile();
-
return !file.isDirectory() &&
-
file.getName().contains("items");
-
};
-
Stream<Path> stream =
-
Files.find(testPath, 100,items
-
);
-
stream.forEach(System.out::println);
3) 擴展的運算符
BinaryOperator 繼承BiFunction
-
BinaryOperator<Integer> add = (n1, n2) -> n1 + n2;
UnaryOperator 繼承Function
-
UnaryOperator<Integer> dda = x -> x + 1;
(三)stream的操作
一、 流的創建 (最終都是依賴底層的StreamSupport類來完成Stream創建)
1) Collection 和數組
Collection.stream()
Collection.parallelStream()
final Stream<String> stream = Arrays.asList("11", "22").stream();
final ArrayList<String> list = Lists.newArrayList();
list.add("33");
final Stream<String> stream3 = list.stream();
final Stream<String> stringStream2 = list.parallelStream();
2) BufferedReader
java.io.BufferedReader.lines()
File file = new File("/Users/qiaozhy/data/qiao.txt");
Reader reader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(reader);
final Stream<String> lines = bufferedReader.lines();
final long count = lines.count();
System.out.println(count);//2
3) 靜態工廠
Arrays.stream(T array)
Stream.of()、iterate()、generate()
java.util.stream.IntStream.range()
java.nio.file.Files.list、find、walk等
Stream.builder()
-
final IntStream intStream1 = Arrays.stream(new int[]{1, 2, 3});
-
-
-
final Stream<String> stringStream = Stream.of("11", "22");
-
-
final Stream<Integer> iterate = Stream.iterate(5, t -> t + 1);
-
iterate.limit(4).forEach(System.out::println);//5,6,7,8
-
-
//supplier 函數式接口的簡化 (Math::random)
-
Stream.generate(Math::random).limit(1).forEach(System.out::println);
-
// 0.48158792725573907
-
-
final IntStream intStream = IntStream.range(1, 3);
-
-
-
final Optional<Path> first = Files.walk(Paths.get("/Users/qiaozhy/data"))
-
.peek(System.out::println).skip(2).findAny();
-
first.orElseThrow(()-> new RuntimeException("結果爲空"));
-
System.out.println(first.get());//Users/qiaozhy/data/工作注意.txt
-
-
final Stream.Builder<Object> builder1 = Stream.builder();
-
builder1.accept(66);
-
builder1.add(2).add(3);
-
builder1.build().forEach(System.out::println); // 66,2,3
4)其他
Pattern.splitAsStream(java.lang.CharSequence)
Random.ints()
JarFile.stream()
BitSet.stream()
-
final Pattern pattern = Pattern.compile(",");
-
final Stream<String> stringStream1 = pattern.splitAsStream("a,y,u");
-
stringStream1.forEach(System.out::println);// a,y,u
-
-
Random random = new Random();
-
final IntStream intStream2 = random.ints(1,20);
-
intStream2.limit(2).forEach(System.out::println); // 5,18
-
-
JarFile jarFile = new JarFile("/Users/qiaozhy/.m2/javacc-5.0.jar");
-
final Stream<JarEntry> stream1 = jarFile.stream();
-
stream1.limit(1).forEach(System.out::println); //META-INF/
-
-
BitSet bitSet = new BitSet();
-
bitSet.set(1);
-
bitSet.set(45);
-
final IntStream stream2 = bitSet.stream();
-
stream2.forEach(System.out::println); // 1,45
二、 中間操作
無狀態(Stateless)操作:每個數據的處理是獨立的,不會影響或依賴之前的數據。如
filter()
、 flatMap()
、 flatMapToDouble()
、 flatMapToInt()
、 flatMapToLong()
、 map()
、 mapToDouble()
、 mapToInt()
、 mapToLong()
、 peek()
、 unordered()
等
unordered操作不會進行任何顯式的打亂流的操作。它的工作是:消除流中必須保持的有序約束,因此允許之後的操作使用 不必考慮有序的優化
有狀態(Stateful)操作:處理時會記錄狀態,比如處理了幾個。後面元素的處理會依賴前面記錄的狀態,或者拿到所有元素才能繼續下去。如
distinct()
、 sorted()
、 sorted(comparator)
、 limit()
、 skip()
等
-
String [] arr = {"a","b","ed","c"};
-
final List<String> collect = Arrays.stream(arr).sorted(Comparator.comparing(String::length)).collect(Collectors.toList());
-
System.out.println(collect);//[a, b, c, ed]
-
final List<String> collect1 = Arrays.stream(arr).sorted(Comparator.reverseOrder()).collect(Collectors.toList());
-
System.out.println(collect1);//[ed, c, b, a]
-
final Optional<String> any = Arrays.stream(arr).distinct().skip(1).limit(1).findAny();
-
any.orElseThrow(()-> new RuntimeException("結果爲空"));
-
final String s = any.get();
-
System.out.println(s);//b
-
String[] words = new String[]{"Hello","World"};
-
Arrays.stream(words)
-
.map(word -> word.split(""))
-
.flatMap(Arrays::stream)
-
.forEach(System.out::print);
-
//HelloWorld
-
List<String> first= Arrays.asList("one", "two", "three", "four");
-
List<String> second= Arrays.asList("A", "B", "C", "D");
-
Stream.of(first,second).flatMap(Collection::stream).forEach(System.out::print);//onetwothreefourABCD
-
Stream.of(1.0,2.0,3.0).mapToInt(Double::intValue).mapToObj(i->"a"+i).forEach(System.out::print);
三、終止操作
非短路操作:處理完所有數據才能得到結果。如
collect()
、 count()
、 forEach()
、 forEachOrdered()
、 max()
、 min()
、 reduce()
、 toArray()
等。
短路(short-circuiting)操作:拿到符合預期的結果就會停下來,不一定會處理完所有數據。如
anyMatch()
、 allMatch()
、 noneMatch()
、 findFirst()
、 findAny()
等
-
List<String> strs = Arrays.asList("a", "a", "a", "a", "b");
-
boolean aa = strs.stream().anyMatch(str -> str.equals("a"));
-
System.out.println(aa);//true
-
boolean bb = strs.stream().allMatch(str -> str.equals("a"));
-
System.out.println(bb);//false
-
boolean cc = strs.stream().noneMatch(str -> str.equals("a"));
-
System.out.println(cc);//false
-
String [] arr = {"a","b","ed","c"};
-
final Optional<String> reduce = Arrays.stream(arr).reduce((a, b) -> a + b);
-
reduce.orElseThrow(()-> new RuntimeException("結果爲空"));
-
System.out.println(reduce.get());//abedc
-
-
List<Integer> numList = Arrays.asList(1,2,3,4,5);
-
int result = numList.stream().reduce(0,(a,b) -> a + b );
-
System.out.println(result);
-
-
List<Integer> numList1 = Arrays.asList(1, 2, 3, 4, 5, 6);
-
ArrayList<String> result1 = numList1.stream().reduce(new ArrayList<String>(),
-
(a, b) -> {
-
a.add("element-" + Integer.toString(b));
-
return a;
-
}, (a, b) -> null);
-
System.out.println(result1);
-
/*
-
需要注意的是這個reduce的簽名還包含第三個參數,一個BinaryOperator<U>類型的表達式。
-
在常規情況下我們可以忽略這個參數,敷衍了事的隨便指定一個表達式即可,目的是爲了通過編譯器的檢查,
-
因爲在常規的stream中它並不會被執行到,然而, 雖然此表達式形同虛設,可是我們也不是把它設置爲null,
-
否者還是會報錯。 在並行stream中,此表達式則會被執行到,在這裏我們不進行講解,因爲我自己也沒用過
-
*/
-
Supplier<Stream<String>> streamSupplier = () -> Stream.of("a","d","b");
-
//輸出的順序與元素的順序嚴格一致
-
streamSupplier.get().parallel().forEachOrdered(System.out::println);//a,d,b
-
//主要的區別在並行流的處理上
-
//輸出的順序不一定(效率更高)
-
streamSupplier.get().parallel().forEach(System.out::println); // d,a,b
-
-
final String[] strings = streamSupplier.get().toArray(String[]::new);
-
System.out.println(Arrays.toString(strings));//[a, d, b]
-
final ArrayList<String> list = Lists.newArrayList();
-
list.add("12");
-
list.add("111");
-
final List<String> collect = list.stream().collect(Collectors.toList());
-
final Set<String> collect1 = list.stream().collect(Collectors.toSet());
-
final Map<Integer, String> collect2 = list.stream().collect(Collectors.toMap(String::length, String::valueOf));
-
-
final Long lo = list.stream().collect(Collectors.counting());
-
-
final IntSummaryStatistics intSummaryStatistics = list.stream().collect(Collectors.summarizingInt(Integer::valueOf));
-
-
final String collect3 = list.stream().collect(Collectors.joining("--"));
-
-
final Optional<String> collect4 = list.stream().collect(Collectors.reducing((x, y) -> x + y));
-
-
final Map<Integer, List<String>> collect5 = list.stream().collect(Collectors.groupingBy(String::length));
-
-
final Optional<Integer> collect6 = list.stream().map(Integer::valueOf).collect(Collectors.maxBy(Integer::max));
(四 )、並行流
在創建Stream時,默認是創建串行流。但是可以使用parallelStream()來創建並行流或者parallel()將串行流轉換成並行流。並行流也可以通過sequential()轉換成串行流。
Java 8 Stream的並行流,本質上還是使用Fork/Join模型
(五)、特殊用法
-
// map的循環方式
-
final HashMap<Object, Object> objectObjectHashMap = Maps.newHashMap();
-
objectObjectHashMap.put("1","2");
-
objectObjectHashMap.put("5","77");
-
objectObjectHashMap.forEach((a,b)->{
-
System.out.println(a);
-
System.out.println(b);
-
});
如果喜歡,歡迎關注我的公衆號:喬志勇筆記