一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 都9102年了,你還用for循環操作集合嗎

都9102年了,你還用for循環操作集合嗎

2021-07-20 16:29cdream Java教程

這篇文章主要給大家介紹了關于java中for循環操作集合使用的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者使用java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧

前言

前段時間公司書架多了一本《java8 實戰》,畢竟久聞lambda的大名,于是借來一閱。這一看,簡直是驚為天人啊,lambda,stream,java8里簡直是滿腦子騷操作,看我的一愣一愣的。我甚至是第一次感覺到了什么叫優雅。

都9102年了,你還用for循環操作集合嗎

本文主要介紹java8中的流處理,看看java8是怎么愉快的玩耍集合的,讓我們來一起感受java8的魅力吧!

我就隨便舉個例子,看看stream有多優雅。

?
1
2
3
4
5
6
7
// 對蘋果按顏色匯總并績數量
map<string, long> applecount = apples.stream()
 .collect(groupingby(apple::getcolor, counting()));
// 過濾掉顏色為黑色的蘋果,并匯總好蘋果的總金額
double sum = apples.stream()
 .filter(i->"black".equals(i.getcolor()))
 .collect(tolist);

一、lambda表達式

雖然本文重點是stream,但是stream中需要傳遞lambda表達式,所以簡單介紹一下lambda表達式。lambda表達式其實就是匿名函數(anonymous function),是指一類無需定義標識符的函數或子程序。

java中匿名函數的表現形式,只留下入參和方法體中的內容

?
1
2
3
4
5
6
// 普通函數
public void run(string s){
 system.out.print(s+"哈哈");
}
// 我不要名字啦!!!
(s)->system.out.print(s+"哈哈")

誒,過去我們都用對象調方法的,你弄這個沒名的東西啥時候用啊?

java中我們通過函數式接口來使用這種匿名函數。

函數式接口

1.java中只包含一個未實現方法的接口。其中可以有與object中同名的方法和默認方法(java8中接口方法可以有默認實現)。

2.java中函數式接口使用@functionalinterface進行注解。runnable、comparator都是函數式接口。

3.java.util.function包下為我們提供很多常用的函數式接口,例如function等。

用法舉例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 實現runnable中的run方法,替代匿名內部類。
runnable r = ()->system.out.print("哈哈");
// 作為參數傳遞。
new thread(()-> system.out.println("haha")).start();
 
arraylist<apple> list = new arraylist<>();
list.foreach(i-> system.out.println(i.getweight()));
 
 
// 簡化策略模式
public static list<apple> filterapples(list<apple> inventory,applepredicate p){
 list<apple> apples = new arraylist<>();
 for(apple apple : inventory){
 if(p.test(apple)){
 apples.add(apple);
 }
 }
 return apples;
}
public class bigapple implement applepredicate{
 @override
 public boolean test(apple a){
 if(a.getweight>10){
 return a
 }
 }
}
// 這是個簡單的策略模式,根據用戶的需要,創建不同的接口applepredicate實現類,調用時傳入不同的實現類就可以,但問題是如果需求過多,創建的實現類也會很多,過于臃腫不方便管理。
xx.filterapple(inventory,new bigapple);
// 使用lambda表達式,不在需要創建bigapple類
xx.filterapple(inventory,i->(i.getweight>10));

使用lambda表達式可以簡化大量的模板代碼,并且可以向方法直接傳遞代碼。

總之

方法出參入參來自函數式接口

?
1
2
3
4
5
6
7
8
9
10
//入參s,返回void
(s)->system.out.println(s);
//入參空,返回void
()->system.out.print("haha");
//入參i,返回i+1
i->i+1
//后面寫代碼塊
apple->{if(apple.getweiht>5) return "big";
 else return "small";
 }

好了,不多啰嗦了,如果感興趣推薦下面的文章或《java8實戰》的前三章。

1.Lambda表達式有何用處?如何使用?

2.java8實戰

二、stream

流是什么?

java api的新成員,它允許你使用聲明式方式處理數據集合(類似sql,通過查詢語句表達,而不是臨時編寫一個實現)。

如果有人說lambda表達式不易于理解,那還勉強可以接受(其實過于復雜的lambda缺失不好閱讀,但通常lambda不會做太復雜的實現),但流真的非常的易懂易用。這個語法糖真的是甜死了。

注意事項:

1.流只能使用一次,遍歷結束就代表這個流被消耗掉了

2.流對集合的操作屬于內部迭代,是流幫助我們操作,而不是外部迭代

3.流操作包含:數據源,中間操作鏈,終端操作三個部分。

基礎流操作

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
list<double> collect = list.stream()
 // 過濾掉黑色的蘋果
 .filter(i -> "black".equals(i.getcolor()))
 // 讓蘋果按照重量個價格排序
 .sorted(comparator.comparing(apple::getweight)
 .thencomparing(i->i.getprice()))
 // 篩選掉重復的數據
 .distinct()
 // 只要蘋果的價格
 .map(apple::getprice)
 // 只留下前兩條數據
 .limit(2)
 // 以集合的形式返回
 .collect(tolist());
// 循環打印列表中元素
list.foreach(i->system.out.print(i));

apple::getprince<=>i -> i.getprince()可以看做是僅涉及單一方法的語法糖,效果與lambda表達式相同,但可讀性更好。

同理

下面列表為常見操作

中間

 

操作 類型 作用 函數描述 函數
filter 中間 過濾 t -> boolean predicate
sorted 中間 排序 (t,t)->int comparator
map 中間 映射 t->r function<t,r>
limit 中間 截斷    
distinct 中間 去重,根據equals方法    
skip 中間 跳過前n個元素    

 

終端

 

操作 類型 作用
foreach 終端 消費流中的每個元素,使用lambda進行操作
count 終端 返回元素個數,long
collect 終端 將流歸約成一個集合,如list,map甚至是integer

 

篩選與切片

?
1
2
3
4
5
6
7
8
9
10
list<string> strings = arrays.aslist("hello", "world");
list<string> collect1 = strings.stream()
 // string映射成string[]
 .map(i -> i.split(""))
 // arrays::stream 數據數組,返回一個流string[]->stream<string>
 // flatmap各數組并不分別映射成一個流,而是映射成流的內容 stream<string>->stream
 .flatmap(arrays::stream)
 .collect(tolist());
system.out.println(collect);
----->輸出 [h, e, l, l, o, w, o, r, l, d]

歸約操作reduce

?
1
2
3
4
5
6
7
8
9
10
11
12
list<integer> integers = arrays.aslist(12, 3, 45, 3, 2,-1);
// 有初始值的疊加操作
integer reduce = integers.stream().reduce(3, (i, j) -> i + j);
integer reduce2 = integers.stream().reduce(5, (x, y) -> x < y ? x : y);
// 無初始值的疊加操作
optional<integer> reduce1 = integers.stream().reduce((i, j) -> i + j);
// 無初始值的最大值
optional<integer> reduce4 = integers.stream().reduce(integer::min);
// 無初始值的最大值
optional<integer> reduce5 = integers.stream().reduce(integer::max);
// 求和
optional<integer> reduce6 = integers.stream().reduce(integer::sum);

reduce做的事情是取兩個數進行操作,結果返回取下一個數操作,以次類推。

optional是java8引入的新類,避免造成空指針異常,在集合為空時,結果會包在optional中,可以用ispresent()方法來判斷是否為空值。

無初始值的情況下可能為空,故返回optional

中間

 

操作 類型 作用 函數描述 函數
flatmap 中間 使通過的流返回內容 t -> boolean predicate

 

終端

 

操作 類型 作用
anymatch 終端 返回boolean,判斷是否有符合條件內容
nonematch 終端 返回boolean,判斷是否無符合條件內容
allmatch 終端 返回boolean,判斷是全為符合條件內容
findany 終端 optional,隨機找一個元素返回
findfirst 終端 optional,返回第一個元素
reduce 終端 optional (t,t)->t 歸約操作

 

數值流

包裝類型的各種操作都會有拆箱操作和裝箱操作,嚴重影響性能。所以java8為我們提供了原始數值流。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 數值流求平均值
optionaldouble average = apples.stream()
 .maptodouble(apple::getprice)
 .average();
// 數值流求和
optionaldouble average = apples.stream()
 .maptodouble(apple::getprice)
 .sum();
// 數值流求最大值,沒有則返回2
double v = apples.stream()
 .maptodouble(apple::getprice)
 .max().orelse(2);
// 生成隨機數
intstream s = intstream.rangeclosed(1,100);

下面列表為常見數值流操作操作

中間

 

操作 類型 作用
rangeclosed(1,100) 中間 生成隨機數(1,100]
range(1,100) 中間 生成隨機數(1,100)
boxed() 中間 包裝成一般流
maptoobj 中間 返回為對象流
maptoint 中間 映射為數值流

 

終端,終端操作與list一般流類似

構建流

值創建

?
1
stream<string> s = stream.of("java","python");

數組創建

?
1
2
int[] i = {2,3,4,5};
stream<int> = arrays.stream(i);

由文件生成,nio api已經更新,以便利用stream api

?
1
stream<string> s = files.lines(paths.get("data.txt"),charset.defaultcharset());

由函數創建流:無限流

?
1
2
3
4
5
6
7
8
// 迭代
stream.iterate(0,n->n+2)
 .limit(10)
 .foreach(system.out::println);
// 生成,需要傳遞實現supplier<t>類型的lambda提供的新值
stream.generate(math.random)
 .limit(5)
 .foreach(system.out::println);

三、總結

至此,本文講述了常見的流操作,目前排序、篩選、求和、歸約等大多數操作我們都能實現了。與過去相比,操作集合變的簡單多了,代碼也變的更加簡練明了。

目前vert.x,spring新出的webflux都通過lambda表達式來簡化代碼,不久的將來,非阻塞式框架的大行其道時,lambda表達式必將變的更加重要!

至于開篇見到的分組!!!下篇文章見~

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對服務器之家的支持。

原文鏈接:https://www.cnblogs.com/cdream-zs/p/10504499.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲国产精品无圣光一区二区 | 欧美成人三级伦在线观看 | 扒开黑女人p大荫蒂老女人 扒开大腿狠狠挺进视频 | 日韩伦理一区 | 97色综合| 成3d漫二区三区四区 | 久久亚洲精品AV无码四区 | 国产精品久久久久久久牛牛 | 日韩精品福利视频一区二区三区 | 放荡的女老板bd中文字幕 | 特级夫妻大片免费在线播放 | 精品性久久| 亚洲天堂男人 | 97超pen个人视频公开视频视 | 亚洲AV 日韩 国产 有码 | 欧美同性video| 国产精品视频人人做人人爱 | 草莓视频幸福宝 | 欧美日韩视频一区三区二区 | 暖暖的视频完整视频韩国免费 | 青青青国产手机在线播放 | 果冻传媒在线免费观看 | 午夜伦伦电影理论片大片 | 亚洲视频中文 | 日韩欧美中文字幕一区二区三区 | 亚洲成在人线视频 | 国产免费丝袜调教视频 | xxxxx性bbbbb欧美 | 亚洲AV无码国产精品色在线看 | 久久99国产精品二区不卡 | 亚洲 色 欧美 爱 视频 日韩 | 国产精品俺来也在线观看了 | 男生操女生漫画 | 国产精品在线 | 91噜噜噜噜色 | 风间由美理论片在线观看 | 欧美性一区二区三区 | 日韩欧美亚洲国产高清在线 | 色综合久久综合网欧美综合网 | 成人影院www在线观看 | 欧美草逼网站 |