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