Java?8?Stream?處理數(shù)據(jù)方法匯總
Stream流
Stream流是什么,為什么要用它
- Stream是Java 8 新引入的一個(gè)包( java.util.stream),它讓我們能用聲明式的方式處理數(shù)據(jù)(集合、數(shù)組等)。
- Stream流式處理相較于傳統(tǒng)方法簡(jiǎn)潔高效,也便于進(jìn)行并發(fā)編程。
- Stream
Stream是Java8的一大亮點(diǎn),是對(duì)容器對(duì)象功能的增強(qiáng),它專注于對(duì)容器對(duì)象進(jìn)行各種非常便利、高效的 聚合操作(aggregate operation)或者大批量數(shù)據(jù)操作。Stream 使用一種類似用 SQL 語(yǔ)句從數(shù)據(jù)庫(kù)查詢數(shù)據(jù)的直觀方式來(lái)提供一種對(duì) Java 集合運(yùn)算和表達(dá)的高階抽象。Stream API借助于同樣新出現(xiàn)的Lambda表達(dá)式,極大的提高編程效率和程序可讀性。同時(shí),它提供串行和并行兩種模式進(jìn)行匯聚操作,并發(fā)模式能夠充分利用多核處理器的優(yōu)勢(shì),使用fork/join并行方式來(lái)拆分任務(wù)和加速處理過(guò)程。所以說(shuō),Java8中首次出現(xiàn)的 java.util.stream是一個(gè)函數(shù)式語(yǔ)言+多核時(shí)代綜合影響的產(chǎn)物。
Stream流的基礎(chǔ)使用
簡(jiǎn)單綜合案例
問(wèn)題和需求:在一個(gè)字符串集合中找出以“阿”開頭的長(zhǎng)度為3的字符串并打印
傳統(tǒng)方法
import java.util.ArrayList; import java.util.List; public class Demo02NormalFilter { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("阿拉貢"); list.add("阿爾玟"); list.add("埃爾隆德"); list.add("凱蘭崔爾"); list.add("瑟蘭督伊"); List<String> zhangList = new ArrayList<>(); for (String name : list) { if (name.startsWith("阿")) { zhangList.add(name); } } List<String> shortList = new ArrayList<>(); for (String name : zhangList) { if (name.length() == 3) { shortList.add(name); } } for (String name : shortList) { System.out.println(name); } } }
這里我們可以看到傳統(tǒng)的方法中含有三個(gè)循環(huán),每一個(gè)作用不同:
- 首先篩選所有姓“阿”的人;
- 然后篩選名字有三個(gè)字的人;
- 最后進(jìn)行對(duì)結(jié)果進(jìn)行打印輸出。
這樣的處理過(guò)程代碼冗長(zhǎng),導(dǎo)致代碼可讀性較差,效率也比較低。 而使用Stream來(lái)進(jìn)行處理就能使代碼優(yōu)雅地多。
Stream流式處理方法
import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; public class Demo02NormalFilter { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("阿拉貢"); list.add("阿爾玟"); list.add("埃爾隆德"); list.add("凱蘭崔爾"); list.add("瑟蘭督伊"); list.stream() .filter(s ‐> s.startsWith("阿")) .filter(s ‐> s.length() == 3) .forEach(System.out::println); } }
利用Stream流中的方法再結(jié)合函數(shù)式接口和Lambda表達(dá)式,我們的代碼就能變得格外簡(jiǎn)潔明了。
獲取流
根據(jù)Collection獲取流
首先, java.util.Collection 接口中加入了default方法 stream 用來(lái)獲取流,所以其所有實(shí)現(xiàn)類均可獲取流。
import java.util.*; import java.util.stream.Stream; public class Demo04GetStream { public static void main(String[] args) { List<String> list = new ArrayList<>(); Stream<String> stream1 = list.stream(); Set<String> set = new HashSet<>(); Stream<String> stream2 = set.stream(); Vector<String> vector = new Vector<>(); Stream<String> stream3 = vector.stream(); } }
根據(jù)Map獲取流
java.util.Map 接口不是 Collection 的子接口,且其K-V數(shù)據(jù)結(jié)構(gòu)不符合流元素的單一特征,所以獲取對(duì)應(yīng)的流需要分key、value或entry等情況:
import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; public class Demo05GetStream { public static void main(String[] args) { Map<String, String> map = new HashMap<>(); //Stream流的轉(zhuǎn)化需要單列數(shù)據(jù),那么我們就先把map里面的數(shù)據(jù)變成單列的再轉(zhuǎn)化為流 Stream<String> keyStream = map.keySet().stream(); Stream<String> valueStream = map.values().stream(); Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream(); } }
根據(jù)數(shù)組獲取流
如果使用的不是集合或映射而是數(shù)組,由于數(shù)組對(duì)象不可能添加默認(rèn)方法,所以 Stream 接口中提供了靜態(tài)方法of ,使用很簡(jiǎn)單:
import java.util.stream.Stream; public class Demo06GetStream { public static void main(String[] args) { String[] array = { "阿拉貢", "阿爾玟", "埃爾隆德", "凱蘭崔爾","瑟蘭督伊" }; Stream<String> stream = Stream.of(array); } }
常用方法
流模型的操作很豐富,這里介紹一些常用的API。這些方法可以被分成兩種: 延遲方法:返回值類型仍然是 Stream 接口自身類型的方法,因此支持鏈?zhǔn)秸{(diào)用。(除了終結(jié)方法外,其余方法均為延遲方法。) 終結(jié)方法:返回值類型不再是 Stream 接口自身類型的方法,因此不再支持類似 StringBuilder 那樣的鏈?zhǔn)秸{(diào)用。接下來(lái)我會(huì)介紹兩個(gè)終結(jié)方法count 和 forEach 方法。
如果想知道更多方法,建議自行參考API文檔
逐一處理:forEach
雖然方法名字叫 forEach ,但是與for循環(huán)中的“for-each”語(yǔ)句是不一樣的 該方法接收一個(gè) Consumer 接口函數(shù),會(huì)將每一個(gè)流元素交給該函數(shù)進(jìn)行處理。
方法簽名
void forEach(Consumer<? super T> action);
基本使用
import java.util.stream.Stream; public class Demo12StreamForEach { public static void main(String[] args) { Stream<String> stream = Stream.of("阿拉貢", "阿爾玟", "埃爾隆德"); stream.forEach(name‐> System.out.println(name)); } }
篩選:filter
可以通過(guò) filter 方法將一個(gè)流轉(zhuǎn)換成另一個(gè)子集流。 該方法接收一個(gè) Predicate 函數(shù)式接口參數(shù)(可以是一個(gè)Lambda或方法引用)作為篩選條件。
方法簽名
Stream<T> filter(Predicate<? super T> predicate);
基本使用
import java.util.stream.Stream; public class Demo07StreamFilter { public static void main(String[] args) { Stream<String> original = Stream.of("阿拉貢", "阿爾玟", "埃爾隆德"); Stream<String> result = original.filter(s ‐> s.startsWith("阿")); } }
在這里通過(guò)Lambda表達(dá)式來(lái)指定了篩選的條件:必須以”阿“開頭。
映射:map
如果需要將流中的元素映射到另一個(gè)流中,可以使用 map 方法。 該接口需要一個(gè) Function 函數(shù)式接口參數(shù),可以將當(dāng)前流中的T類型數(shù)據(jù)轉(zhuǎn)換為另一種R類型的流。
方法簽名
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
基本使用
import java.util.stream.Stream; public class Demo08StreamMap { public static void main(String[] args) { Stream<String> original = Stream.of("10", "12", "18"); Stream<Integer> result = original.map(str‐>Integer.parseInt(str)); } }
這段代碼中, map 方法的參數(shù)通過(guò)方法引用,將字符串類型轉(zhuǎn)換成為了int類型(并自動(dòng)裝箱為 Integer 類對(duì)象)。
統(tǒng)計(jì)個(gè)數(shù):count
正如舊集合 Collection 當(dāng)中的 size 方法一樣,流提供 count 方法來(lái)數(shù)一數(shù)其中的元素個(gè)數(shù)。 該方法返回一個(gè)long值代表元素個(gè)數(shù)(不再像舊集合那樣是int值)。
方法簽名
long count();
基本使用
import java.util.stream.Stream; public class Demo09StreamCount { public static void main(String[] args) { Stream<String> original = Stream.of("阿拉貢", "阿爾玟", "埃爾隆德"); Stream<String> result = original.filter(s ‐> s.startsWith("阿")); System.out.println(result.count()); // 2 } }
取用前幾個(gè):limit
limit 方法可以對(duì)流進(jìn)行截取,只取用前n個(gè)。 參數(shù)是一個(gè)long型,如果集合當(dāng)前長(zhǎng)度大于參數(shù)則進(jìn)行截??;否則不進(jìn)行操作。
方法簽名
Stream<T> limit(long maxSize);
基本使用
import java.util.stream.Stream; public class Demo10StreamLimit { public static void main(String[] args) { Stream<String> original = Stream.of("阿拉貢", "阿爾玟", "埃爾隆德"); Stream<String> result = original.limit(2); System.out.println(result.count()); // 2 } }
跳過(guò)前幾個(gè):skip
如果希望跳過(guò)前幾個(gè)元素,可以使用 skip 方法獲取一個(gè)截取之后的新流。 如果流的當(dāng)前長(zhǎng)度大于n,則跳過(guò)前n個(gè);否則將會(huì)得到一個(gè)長(zhǎng)度為0的空流。
方法簽名
Stream<T> skip(long n);
基本使用
import java.util.stream.Stream; public class Demo11StreamSkip { public static void main(String[] args) { Stream<String> original = Stream.of("阿拉貢", "阿爾玟", "埃爾隆德"); Stream<String> result = original.skip(2); System.out.println(result.count()); // 1 } }
組合:concat
如果有兩個(gè)流,希望合并成為一個(gè)流,那么可以使用 Stream 接口的靜態(tài)方法 concat 。
這是一個(gè)靜態(tài)方法,與 java.lang.String 當(dāng)中的 concat 方法是不同的。
方法簽名
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T>b)
基本使用
import java.util.stream.Stream; public class Demo12StreamConcat { public static void main(String[] args) { Stream<String> streamA = Stream.of("阿拉貢"); Stream<String> streamB = Stream.of("阿爾玟"); Stream<String> result = Stream.concat(streamA, streamB); } }
到此這篇關(guān)于Java 8 Stream 優(yōu)雅地處理數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Java Stream 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
剖析Spring WebFlux反應(yīng)式編程設(shè)計(jì)及工作原理
這篇文章主要為大家介紹了Spring WebFlux反應(yīng)式編程模型工作原理的剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-02-02SpringMVC中使用@PathVariable綁定路由中的數(shù)組的方法
這篇文章主要介紹了SpringMVC中使用@PathVariable綁定路由中的數(shù)組的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07java中關(guān)于文本文件的讀寫方法實(shí)例總結(jié)
這篇文章主要介紹了java中關(guān)于文本文件的讀寫方法,實(shí)例總結(jié)了Java針對(duì)文本文件讀寫的幾種常用方法,并對(duì)比了各個(gè)方法的優(yōu)劣及特點(diǎn),具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11springboot全局字符編碼設(shè)置解決亂碼問(wèn)題
這篇文章主要介紹了springboot全局字符編碼設(shè)置解決亂碼問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09JAVA 對(duì)象創(chuàng)建與對(duì)象克隆
這篇文章主要介紹了JAVA 對(duì)象創(chuàng)建與對(duì)象克隆,new 創(chuàng)建、反射、克隆、反序列化,克隆它分為深拷貝和淺拷貝,通過(guò)調(diào)用對(duì)象的 clone方法,進(jìn)行對(duì)象的克隆,下面來(lái)看看文章的詳細(xì)內(nèi)容吧2022-02-02java objectUtils 使用可能會(huì)出現(xiàn)的問(wèn)題
這篇文章主要介紹了java objectUtils 使用可能會(huì)出現(xiàn)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02