Java8的兩個重大改變,一個是Lambda表達式,另一個就是本節要講的Stream API表達式。Stream 是Java8中處理集合的關鍵抽象概念,它可以對集合進行非常複雜的查找、過濾、篩選等操作。
1、Stream的操作步驟
Stream有如下三個操作步驟:
一、創建Stream
從一個數據源,如集合、數組中獲取流。
二、中間操作
一個操作的中間鏈,對數據源的數據進行操作。
三、終止操作
一個終止操作,執行中間操作鏈,併產生結果。
要注意的是,對流的操作完成後需要進行關閉操作(或者用JAVA7的try-with-resources)。
public static void main(String[] args) {
// 1)找到年齡大於18歲的人並輸出;
personList.stream().filter((p) -> p.getAge() > 18).forEach(System.out::println);
System.out.println("-------------------------------------------");
// 2)找出所有中國人的數量
long chinaPersonNum = personList.stream().filter((p) -> p.getCountry().equals("中國")).count();
System.out.println("中國人有:" + chinaPersonNum + "個");
}
上面的例子表示,我要查找personList集合中,所有國籍爲中國的人數量;遍歷輸出所有年齡大於18的人員信息。
2、Stream中間操作--篩選與切片
- filter:接收Lambda,從流中排除某些操作;
- limit:截斷流,使其元素不超過給定對象
- skip(n):跳過元素,返回一個扔掉了前n個元素的流,若流中元素不足n個,則返回一個空流,與limit(n)互補
- distinct:篩選,通過流所生成元素的hashCode()和equals()去除重複元素。
2.1 limit舉例
需求,從Person列表中取出兩個女性。
1 personList.stream().filter((p) -> p.getSex() == 'F').limit(2).forEach(System.out::println);
輸出結果爲:
Person(name=歐陽雪, age=18, country=中國, sex=F)
Person(name=Harley, age=22, country=英國, sex=F)
2.2 skip舉例
從Person列表中從第2個女性開始,取出所有的女性。
1 personList.stream().filter((p) -> p.getSex() == 'F').skip(1).forEach(System.out::println);
輸出結果爲:
Person(name=Harley, age=22, country=英國, sex=F)
Person(name=小梅, age=20, country=中國, sex=F)
Person(name=何雪, age=21, country=中國, sex=F)
2.3 distinct舉例
1 personList.stream().filter((p) -> p.getSex() == 'M').distinct().forEach(System.out::println);
輸出結果爲:
Person(name=Tom, age=24, country=美國, sex=M)
Person(name=向天笑, age=20, country=中國, sex=M)
Person(name=李康, age=22, country=中國, sex=M)
男性中有兩個李康,去除掉了一個重複的。
3、Stream中間操作--映射
- map--接收Lambda,將元素轉換成其他形式或提取信息。接收一個函數作爲參數,該函數會被應用到每個元素上,並將其映射成一個新的元素。
- flatMap--接收一個函數作爲參數,將流中的每個值都換成另一個流,然後把所有流連接成一個流
3.1 map舉例
String[] words = new String[]{"Hello","World"};
List<String[]> a = Arrays.stream(words)
.map(word -> word.split(""))
.distinct()
.collect(toList());
a.forEach(System.out::print);
代碼輸出爲:[Ljava.lang.String;@12edcd21[Ljava.lang.String;@34c45dca (返回一個包含兩個String[]的list)
這個實現方式是由問題的,傳遞給map方法的lambda爲每個單詞生成了一個String[](String列表)。因此,map返回的流實際上是Stream<String[]> 類型的。你真正想要的是用Stream<String>來表示一個字符串。
下方圖是上方代碼stream的運行流程
3.2 flatMap舉例(對流扁平化處理)
String[] words = new String[]{"Hello","World"};
List<String> a = Arrays.stream(words)
.map(word -> word.split(""))
.flatMap(Arrays::stream)
.distinct()
.collect(toList());
a.forEach(System.out::print);
結果輸出:HeloWrd
使用flatMap方法的效果是,各個數組並不是分別映射一個流,而是映射成流的內容,所有使用map(Array::stream)時生成的單個流被合併起來,即扁平化爲一個流。
下圖是運用flatMap的stream運行流程,
其他Stream操作,請參考以下博客:
https://www.cnblogs.com/wuhenzhidu/p/10740091.html
https://blog.csdn.net/weixin_38361347/article/details/90247695
https://blog.csdn.net/weixin_33860722/article/details/93596115