一. 基本概念
二. 串行流和並行流
三. 中間操作 和 最終操作
一. 基本概念
1.1 為什么加入 集合的流式操作
JDK8 的Stream 是一個受到 函數式編程 和 多核時代影響而產生的東西。很多時候我們需要到底層返回數據,上層再對數據進行遍歷,進行一些數據統計,但是之前的Java API 中很少有這種方法,這就需要我們自己來 Iterator 來遍歷,如果JDK 能夠為我們提供一些這種方法,並且能夠為我們優化就好了。
所以JDK8加入 了 java.util.stream包,實現了集合的流式操作,流式操作包括集合的過濾,排序,映射等功能。根據流的操作性,又可以分為 串行流 和 並行流。根據操作返回的結果不同,流式操作又分為中間操作和最終操作。大大方便了我們對於集合的操作。
- 最終操作:返回一特定類型的結果。
- 中間操作:返回流本身。
1.2 什么是 流
Stream 不是 集合元素,也不是數據結構,它相當於一個 高級版本的 Iterator,不可以重復遍歷里面的數據,像水一樣,流過了就一去不復返。它和普通的 Iterator 不同的是,它可以並行遍歷,普通的 Iterator 只能是串行,在一個線程中執行。
二. 串行流和並行流:
串行流操作在一個線程中依次完成。並行流在多個線程中完成,主要利用了 JDK7 的 Fork/Join 框架來拆分任務和加速處理。相比串行流,並行流可以很大程度提高程序的效率。
三. 中間操作 和 最終操作
中間操作:
- filter(): 對元素進行過濾
- sorted():對元素排序
- map():元素映射
- distinct():去除重復的元素
最終操作:
- forEach():遍歷每個元素。
- reduce():把Stream 元素組合起來。例如,字符串拼接,數值的 sum,min,max ,average 都是特殊的 reduce。
- collect():返回一個新的集合。
- min():找到最小值。
- max():找到最大值。
3.1 filter() 對元素進行過濾
Demo(有一鏈表,{1,2,3,4,5},把偶數過濾掉):
輸出:
package com.dxz.study.jdk8; import java.util.ArrayList; import java.util.List; public class Stream { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); for(int i = 1 ; i <= 5; ++i){ list.add(i); } list.stream().filter(param -> (int)param % 2 == 1) .forEach(System.out::println); } }
3.2 sorted() 對元素進行排序
Demo(有一鏈表,{2,3,1,5,4},從小到大排序):
輸出:
那么,自定義比較函數即可,如下代碼:
輸出為:
輸出:
public static void sorted() { List list = new ArrayList(); list.add(2); list.add(3); list.add(1); list.add(5); list.add(4); list.stream().sorted().forEach(System.out::println); }
1 2 3 4 5
Ps1: 此時為升序,那么有時候我們可能會需要到降序,此時做法可以如下:
流除了提供默認的升序 sorted() 方法,也提供了:
public static void test2() { List list = new ArrayList(); list.add(2); list.add(3); list.add(1); list.add(5); list.add(4); // list.stream().sorted().forEach(System.out::println); list.stream().sorted( (param1,param2) -> ((int)param1 < (int)param2 ? 1 : -1 ) ) .forEach(System.out::println); }
3.3 map() 元素映射
也就是說,原來的鏈表的每個元素可以按照規則變成相應的元素。
Demo(鏈表 (1,0),變成 true,false):
public static void test3() { List list = new ArrayList(); list.add(1); list.add(0); list.stream().map( param -> (int)param == 1 ? true:false ) .forEach(System.out::println); }
true false
3.4 distinct() 去除重復元素
Demo:
public static void test4() { List list = new ArrayList(); list.add(1); list.add(1); list.add(0); list.stream().distinct().forEach(System.out::println); }
1 0
3.5 reduce() :把Stream 元素組合起來。
Demo(從1加到5):
public static void test5() { List list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); System.out.println(list.stream().reduce((param1, param2) -> (int) param1 + (int) param2).get()); }
15
注意,reduce() 返回一個 Optional 類型的對象,可以通過 get() 方法獲得值。
3.6 collect() :返回一個新的集合
Demo(先把 list 集合的 奇數去掉,然后把剩下的偶數返回到 _list 集合中):
輸出:
public static void test6() { List list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); List _list = (List) list.stream().filter((param) -> (int) param % 2 == 0).collect(Collectors.toList()); _list.forEach(System.out::println); }
2 4
3.7 min(),max() 找到最大值最小值
public static void test7() { List list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); System.out.println(list.stream().min((param1, param2) -> (int) param1 > (int) param2 ? 1 : -1).get()); System.out.println(list.stream().max((param1, param2) -> (int) param1 > (int) param2 ? 1 : -1).get()); }
1 5
注意, min(),max() 方法也是返回 Optional 對象, 可以通過 get() 方法返回值。
總結:
1. 流式操作的引入:提高執行效率(並行),方便編碼(有很多API 可用),提高可讀性。
2. 流的分類:可以分為串行流和並行流;對於操作:可以分為中間操作和最終操作
3. 流API:
中間操作:
2. 流的分類:可以分為串行流和並行流;對於操作:可以分為中間操作和最終操作
3. 流API:
中間操作:
filter(): 對元素進行過濾;
sorted():對元素排序;
map():元素映射;
distinct():去除重復的元素 。
最終操作:
forEach():遍歷每個元素;
reduce():把Stream 元素組合起來。例如,字符串拼接,數值的 sum,min,max ,average 都是特殊的 reduce。
collect():返回一個新的集合。
min():找到最小值。
max():找到最大值。
Ps1:除了上面介紹的方法,還有如下方法:
- Intermediate:
- Terminal:
- Short-circuiting:
Ps2:在JDK 8 中的 Comparator 接口中,既有 equals 方法,也有 compare 方法,為什么還可以聲明為函數式接口?有哪位大神指導麻煩告知一下。
參考:
2. Java 8 中的Stream API 詳解:
https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/