Java流處理stream使用詳解
基本流
foreach 實(shí)現(xiàn)了外部迭代,它是建立于集合的基礎(chǔ)上;
stream 流實(shí)現(xiàn)的是內(nèi)部迭代
中間操作與終端操作
對(duì)任意集合使用 stream() 方法來(lái)使用流操作來(lái)對(duì)其進(jìn)行內(nèi)部迭代;
中間操作:流水線上的中間操作,他會(huì)返回一個(gè) stream
終端操作:一般位于流水線末尾,輸出一個(gè)非 stream 類型的值
這是下方代碼的完整運(yùn)行過(guò)程:
- 首先使用 stream 方法使用流來(lái)處理集合 names
- 使用過(guò)濾器 filter,過(guò)濾出字符串中含有字符 a 的字符串
- distinct 進(jìn)行去重
- toList 將以上所有中間操作過(guò)后得到的結(jié)果進(jìn)行匯總,轉(zhuǎn)換成 list 并輸出
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
strings.add("asd");
strings.add("asd");
strings.add("qwe");
List<String> names = strings.stream()
// 過(guò)濾
.filter(d -> {
return d.contains("a");
})
// 去重
.distinct()
// 轉(zhuǎn)換成列表
.toList();
for (String name : names) System.out.println(name); // 輸出:asd
}一些常見(jiàn)的終端操作
foreach:消費(fèi)流中所有元素并使用 lambda,該操作返回 void
count:返回流中的元素個(gè)數(shù),返回類型為 long
collect:把流處理結(jié)果返回成一個(gè)集合,譬如 toList 方法
進(jìn)階流
篩選各異的元素
distinct 進(jìn)行去重
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 1, 2, 4, 2, 2);
numbers.stream()
.filter(i -> i % 2 == 0)
.distinct()
.forEach(System.out::println);
}
截?cái)?/h3>
limit,做多返回前 n 個(gè)元素
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 1, 2, 4, 2, 2);
numbers.stream()
.limit(3)
.forEach(System.out::println);
}跳過(guò)元素
skip(4) 表示跳過(guò)前四個(gè)元素,并返回后面所有的元素;
由于代碼都差不多,這里不做過(guò)多演示
映射流
map
map 接收一個(gè)函數(shù)作為參數(shù),他將對(duì)集合中的每個(gè)元素應(yīng)用該函數(shù),并返回該函數(shù)規(guī)定的值;
如下代碼使用 map 獲取了每個(gè) dish 的名稱并返回它,由此生成了由 dishname 構(gòu)成的列表
public static void main(String[] args) {
List<Dish> dishes = new ArrayList<>();
dishes.add(new Dish("apple", true, 120, Dish.Type.FRUIT));
dishes.add(new Dish("pork", false, 900, Dish.Type.MEAT));
dishes.add(new Dish("fish", false, 400, Dish.Type.FISH));
List<String> dishNames = dishes.stream()
.map(Dish::getName)
.toList();
dishes.forEach(System.out::println);
}flatMap
map 是將每個(gè)元素都映射成了一個(gè)流;
flatMap 是將每個(gè)元素都放如同一個(gè)流中!
以下代碼實(shí)現(xiàn):提取單詞表中出現(xiàn)的單詞;
Arrays.stream 可以將集合轉(zhuǎn)換成流的形式;
應(yīng)當(dāng)首先應(yīng)用 map,將元素進(jìn)行映射后,在使用 flatMap 把這些映射完畢的元素全部裝入一個(gè)統(tǒng)一的流里面!
public static void main(String[] args) {
// 創(chuàng)建單詞表
String[] words = {"goodbye", "hello", "night"};
// 將單詞表轉(zhuǎn)換成流的形式
Stream<String> swords = Arrays.stream(words);
// 首先使用map,將所有字母都一一分割來(lái)開(kāi)
List<String> strings = swords.map(word -> word.split(""))
// 使用扁平map,將提取到的字母裝入一個(gè)流中
.flatMap(Arrays::stream)
// 字母去重
.distinct()
// 轉(zhuǎn)換成列表
.toList();
strings.forEach(System.out::println);
}匹配
anyMatch 能應(yīng)答:流中是否有至少有一個(gè)元素能匹配所給定的謂詞(方法引用)
public static void main(String[] args) {
List<Dish> dishes = Menu.getMenu();
if(dishes.stream().anyMatch(Dish::isVegetarian)){
System.out.println("至少有一個(gè)素菜!");
}
}
全匹配與非全匹配
allMatch 方法檢查謂詞能否匹配所有元素;
noneMatch 方法作用與 allMatch 方法完全相反;
Optional
findAny
findAny 方法默認(rèn)返回一個(gè) Optional<T>
ifPresent 會(huì)在值存在的時(shí)候執(zhí)行后面的 lambda 函數(shù)
public static void main(String[] args) {
List<Dish> dishes = Menu.getMenu();
dishes.stream()
.filter(Dish::isVegetarian)
.findAny()
.ifPresent(d -> System.out.println(d.getName()));
}
findFirst
顧名思義,找到集合中的第一個(gè)元素
歸約
求和
下方展示了三種求和方式:
- 直接使用 arrays 函數(shù)自帶的 sum 方法求和;
- 使用 reduce,參數(shù)一表示初始值,參數(shù)二為對(duì)值的操作
- 同樣使用 reduce,但是引入了謂詞!
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5};
int sum = Arrays.stream(nums).sum();
int sum2 = Arrays.stream(nums)
.reduce(0, (a, b) -> a + b);
int sum3 = Arrays.stream(nums)
.reduce(0, Integer::sum);
}歸約相關(guān)闡發(fā)
map+reduce 常被作為一種形式來(lái)進(jìn)行并行化;
使用 reduce 進(jìn)行的迭代被內(nèi)部抽象化掉了,所以有益于并行的執(zhí)行;
parallelStream 可以方便的進(jìn)行并行操作,但是也帶來(lái)了同步不安全的隱患;
數(shù)值流
使用 mapToInt 返回特化的 IntStream
public static void main(String[] args) {
List<Dish> dishes = Menu.getMenu();
int sum = dishes.stream()
.mapToInt(Dish::getCalories)
.sum();
}boxed
將某個(gè)特化流轉(zhuǎn)換成一般流,可以使用 boxed 方法
IntStream is = dishes.stream().mapToInt(Dish::getCalories); Stream<Integer> sis = is.boxed();
range
針對(duì)特化流 IntStream 和 LongStream,他們均有 range 和 rangeClose 方法;
range:遍歷范圍內(nèi)所有數(shù)字除了右邊界數(shù)字
rangeClose:遍歷包含右邊界的所有范圍數(shù)字
下面代碼展示了獲取 1-100 內(nèi)所有偶數(shù)的個(gè)數(shù)
IntStream evenNumbers = IntStream.rangeClosed(1,100)
.filter(n->n%2==0);
System.out.println(evenNumbers.count());
構(gòu)建流
創(chuàng)建流的三種方式
Stream.of(xxx) 通過(guò)數(shù)值直接構(gòu)建;
Arrays.stream() 數(shù)組創(chuàng)建;
File.lines() 通過(guò)獲取的文件內(nèi)容創(chuàng)建;
到此這篇關(guān)于Java流處理stream使用詳解的文章就介紹到這了,更多相關(guān)Java stream內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java基于Socket實(shí)現(xiàn)多人聊天室
這篇文章主要為大家詳細(xì)介紹了Java基于Socket實(shí)現(xiàn)多人聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09
Java中的Static class詳解及實(shí)例代碼
這篇文章主要介紹了 Java中的Static class詳解及實(shí)例代碼的相關(guān)資料,在Java中我們可以有靜態(tài)實(shí)例變量、靜態(tài)方法、靜態(tài)塊。類也可以是靜態(tài)的,需要的朋友可以參考下2017-03-03
jdbc連SQL?server顯示1433端口連接失敗圖文解決方法
這篇文章主要給大家介紹了關(guān)于jdbc連SQL?server顯示1433端口連接失敗的圖文解決方法,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-06-06
詳解Java中如何定義和訪問(wèn)靜態(tài)字段和方法
在面向?qū)ο蟮某绦蛟O(shè)計(jì)中,我們通常使用類來(lái)創(chuàng)建對(duì)象,類中有許多成員變量和方法,它們是直接屬于對(duì)象實(shí)例的,與之對(duì)應(yīng)的還有一類成員,那就是靜態(tài)成員,本文就來(lái)和大家聊聊Java是如何定義訪問(wèn)靜態(tài)成員的吧2023-05-05
Java并發(fā)volatile可見(jiàn)性的驗(yàn)證實(shí)現(xiàn)
這篇文章主要介紹了Java并發(fā)volatile可見(jiàn)性的驗(yàn)證實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05

