详解Java8中流(Stream)的使用
文章列表
- 一、回憶Lambda表達(dá)式
- 二、什么是流
- 1、流只能遍歷一次
- 2、外部迭代和內(nèi)部迭代
- 三、流操作
- 1、謂詞篩選
- 2、篩選各異元素
- 3、截段流
- 4、跳過元素
- 5、map和flatMap
- 6、查找和匹配
- 7、歸約reduce
寫在前面:
我是「境里婆娑」。我還是從前那個(gè)少年,沒有一絲絲改變,時(shí)間只不過是考驗(yàn),種在心中信念絲毫未減,眼前這個(gè)少年,還是最初那張臉,面前再多艱險(xiǎn)不退卻。
寫博客的目的就是分享給大家一起學(xué)習(xí)交流,如果您對 Java感興趣,可以關(guān)注我,我們一起學(xué)習(xí)。
前言:還沒接觸過流的同學(xué)可以深入研究下此篇文章,讓你在寫代碼過程中可以讓你達(dá)到事半功倍效果。
一、回憶Lambda表達(dá)式
在學(xué)習(xí)流之前,我們先回憶一下Lambda表達(dá)式和函數(shù)式接口
| 布爾表達(dá)式 | (List< String> list -> list.isEmpty()) | Predicate<(List< String>> |
| 創(chuàng)建對象 | () -> new Car() | Supplier< Car> |
| 消費(fèi)一個(gè)對象 | (Car car) -> System.out.println(car.getColor) | Consumer< Car> |
| 從一個(gè)對象提取 | (String s) -> s.length() | Function< String,Integer> |
| 合并兩個(gè)值 | (int a,int b) ->a*b | IntBinaryOperator |
| 比較兩個(gè)值對象 | (Apple a1,Apple a2) -> a1.getWeigth().compareTo(a2.getWeigth()) | Comparator< Apple>或BiFunction< Apple,Apple,Integer> |
二、什么是流
流是Java 新的API,它允許你以聲明性方式處理數(shù)據(jù)集合??梢园蚜骺醋魇潜闅v數(shù)據(jù)集合的高級迭代器。另外,流還可以透明的并行處理,無需寫任何多線程代碼。
public class Car {private String color;private String brand; }例Java7之前,選出小汽車顏色代碼如下:
List<Car> cars = Arrays.asList(new Car("bule", "aodi"), new Car("red", "BMW"), new Car("white", "benw")); List<String> list = new ArrayList<>(); for (Car car : cars) {list.add(car.getColor()); }例Java8之后可以如下:
List<String> collect = cars.stream().map(Car::getColor).collect(toList());總結(jié)一下:Java8中的Stream API可以讓你寫出這樣的代碼
- 聲明性 更簡潔,更易懂
- 可復(fù)合,更靈活
- 可并行,性能更好
看完上面代碼我們還是有疑惑,流到底是什么呢?簡短定義就是“從支持?jǐn)?shù)據(jù)處理操作的源生成的元素序列”
- 元素序列,就像集合一樣,流提供一個(gè)接口,可以訪問特定元素類型的有序值。集合是數(shù)據(jù)結(jié)構(gòu),目的是以特定的時(shí)間/空間復(fù)雜度存儲和訪問元素。但流的目的在于表達(dá)計(jì)算??偟膩碚f集合講的是數(shù)據(jù),而流講的是計(jì)算。
- 源,流會使用一個(gè)提供數(shù)據(jù)的源,如集合、 數(shù)組或輸入輸出資源。
- 數(shù)據(jù)處理操作,流的數(shù)據(jù)處理功能支持類似數(shù)據(jù)庫的操作,以及函數(shù)式編程語言中的常用操作,如filter、map、reduce、find、match、sort。流操作可以順序執(zhí)行,也可以并行執(zhí)行。
- 流水線,很多流操作本身會返回一個(gè)流,這樣多個(gè)操作就可以連接起來,形成一個(gè)大的流水線。
- 內(nèi)部迭代,與使用迭代器顯式迭代集合不同,流的迭代操作是在背后執(zhí)行的。
1、流只能遍歷一次
流還有一個(gè)特點(diǎn)就是只能遍歷一次。遍歷完之后,我們說這個(gè)流已經(jīng)被消費(fèi)掉了。
2、外部迭代和內(nèi)部迭代
使用Collection接口需要用戶去做迭代比如for-each,這稱為外部迭代。相反,Streams庫使用內(nèi)部迭代。
采用內(nèi)部迭代,項(xiàng)目可以透明地并行處理,或者用優(yōu)化的順序進(jìn)行處理,要是使用 Java 過去的外部迭代方法,這些優(yōu)化都是很困難的
三、流操作
1、謂詞篩選
Streams接口支持filter方法,該操作會接受一個(gè)謂詞作為參數(shù)。
List<Car> aodi = cars.stream().filter(car -> car.getBrand().equals("aodi")).collect(toList());2、篩選各異元素
流還支持一個(gè)叫distinct的方法,它會返回一個(gè)元素各異的流。以下代碼會篩選出所有基數(shù)。
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4); numbers.stream() .filter(i -> i % 2 != 0) .distinct() .forEach(System.out::println);3、截段流
流支持limit方法,該方法會返回一個(gè)不超過給定長度的流。所需要的長度作為參數(shù)傳遞給limit。
List<Car> aodi = cars.stream().filter(car -> car.getBrand().equals("aodi")).limit(3).collect(toList());請注意limit也可以用在無序流上。比如源是一個(gè)Set,這種情況下,limit的結(jié)果不會以人物順序排列。
4、跳過元素
流還支持skip方法,返回一個(gè)扔掉了前n個(gè)元素的流。如果流中的元素不足n,則返回一個(gè)空流。注意。limit和skip是互補(bǔ)的。
List<Car> aodi = cars.stream().filter(car -> car.getBrand().equals("aodi")).skip(3).collect(toList());5、map和flatMap
map和flatMap如何選用:假如你的集合流中包含子集合,那么使用flatMap可以返回該子集合的集合流
words.stream() .map(word -> word.split("")) .flatMap(Arrays::stream) .distinct() .collect(toList());如果想詳細(xì)了解map和flatMap區(qū)別請看這篇文章:java8中map和flatMap區(qū)別
6、查找和匹配
另一個(gè)常見的數(shù)據(jù)處理套路是看看數(shù)據(jù)集中的某些元素是否匹配一個(gè)給定的屬性。
- anyMatch,流中是否有一個(gè)元素能匹配到給定的謂詞
- allMatch,是否匹配所有元素
- noneMatch,確保流中沒有任何元素與給定的謂詞匹配
allMatch、anyMatch、noneMatch都用到了我們所謂的短路,這就是大家熟悉java中的&&和||運(yùn)算符。
- findAny返回當(dāng)前流中的任意元素。
- findFirst()查出第一個(gè)元素
findAny()和findFirst()都會返回一個(gè)Optional泛型的對象。
Optional 是一個(gè)容器類,代表一個(gè)值存在或不存在。Optional方法如下:
- isPresent()將在Optional包含值的時(shí)候返回true。否則返回false
- ifPresent()會在值存在的時(shí)候執(zhí)行給定代碼塊。
- get()會在值存在返回值。
- orElse()會在值存在時(shí)返回值。否則返回一個(gè)默認(rèn)值。
7、歸約reduce
reduce是一個(gè)終端操作,比如我們做求和操作。
int sum = numbers.stream().reduce(0, (a, b) -> a + b);比如求最大值和最小值
Optional<Integer> min = numbers.stream().reduce(Integer::max); Optional<Integer> min = numbers.stream().reduce(Integer::min);至此我們把流的基本操作都介紹完。下面我們總結(jié)一下哪些是中間操作哪些是終端操作。
———————————————————————————
如果喜歡這篇文章的話請關(guān)注我!
總結(jié)
以上是生活随笔為你收集整理的详解Java8中流(Stream)的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 警惕由于使用YYYY-MM-dd引发的一
- 下一篇: 一份MyBaits框架PDF文档,阿里架