文:恕我直言汞幢,我懷疑你沒怎么用過Stream流
注:中國傳統(tǒng)文化,先仔細(xì)看微谓,若有用森篷,再點(diǎn)贊, 給自己一點(diǎn)思考的時間
注:微信搜索:CodeCow豺型,關(guān)注這個非常 SAO 的程序員
我們是否一樣 仲智?
想當(dāng)年,小編在自學(xué)Java語言看書時姻氨,關(guān)于 “Stream流” 這一塊的知識點(diǎn)可能都有點(diǎn) “輕敵” 钓辆,覺得這塊內(nèi)容 “ so easy ”非常簡單,一眼而過肴焊。
殊不知前联,撿了芝麻,丟了西瓜娶眷;并且在小編代碼中似嗤,也從未有過“Stream流” 地位可言;卻渾然不知届宠,java8的一哥“Stream流”双谆,在旁暗自嘲諷 “ 這TM是誰,太菜了 ” 席揽。
就拿小編上篇文章《兩年了顽馋,才知道如何實(shí)現(xiàn)多線程,哎 》來講幌羞,也是一堆連環(huán) for 循環(huán)的SAO操作寸谜,何曾想過Stream流的感受
java 8 一哥 ?
在Java 8中,得益于 Lambda 所帶 來的 函數(shù)式編程属桦,應(yīng)運(yùn)而生了一個全新的概念——Stream流熊痴,用于解決已有集合類庫既有的弊端他爸。
首先
關(guān)于Stream流上的操作,大體可以分為兩種:
- 中間操作(Intermediate)果善,其返回結(jié)果都是Stream诊笤,故可以多個中間操作疊加;
- 終止操作(Terminal)巾陕,其返回結(jié)果是我們最終需要的數(shù)據(jù)讨跟,故只能有一個終止操作
其次
Stream流是一個來自數(shù)據(jù)源的元素隊列,例如
- 元素是特定類型的對象鄙煤,形成一個隊列晾匠。 Java中的Stream并不會存儲元素,而是按需計算梯刚。
- 數(shù)據(jù)源 流的來源凉馆。 可以是集合,數(shù)組 等亡资。
再者
Stream流和以前的 Collection操作不同澜共, Stream操作還有兩個基礎(chǔ)的特征:
- Pipelining:中間操作都會返回流對象本身。 這樣多個操作可以串聯(lián)成一個管道锥腻, 如同流式風(fēng)格(fluent style)咳胃。 這樣做可以對操作進(jìn)行優(yōu)化, 比如延遲執(zhí)行(laziness) 和 短路( short-circuiting)旷太。
- 內(nèi)部迭代: 以前對集合遍歷都是通過Iterator或者增強(qiáng)for的方式, 顯式的在集合外部進(jìn)行迭代展懈, 這叫做外部迭代。 Stream提供了內(nèi)部迭代的方式供璧,流可以直接調(diào)用遍歷方法存崖。
最后
嘍一眼Stream流的接口繼承關(guān)系
[圖片上傳失敗...(image-b7eb65-1596705940785)]
所以,當(dāng)我們使用一個流的時候睡毒,通常包括三個基本步驟:獲取一個數(shù)據(jù)源(source)→ 數(shù)據(jù)轉(zhuǎn)換→執(zhí)行操作獲取想要的結(jié)果
但来惧,每次轉(zhuǎn)換原有 Stream 對象不改變,返回一個新的 Stream 對象(可以有多次轉(zhuǎn)換)演顾,這就允許對其操作可以 像鏈條一樣排列供搀,變成一個管道。
注意:“Stream流”其實(shí)是一個集合元素的函數(shù)模型钠至,它并不是集合葛虐,也不是數(shù)據(jù)結(jié)構(gòu),其本身并不存儲任何 元素(或其地址值)棉钧。
因此屿脐,Stream流的一哥地位,并非空穴來風(fēng)
接下來,硬核SAO操作的诵,別眨眼
[圖片上傳失敗...(image-a750dd-1596705940785)]
為什么需要Stream流
常用的for循環(huán)它不香嗎万栅?為啥非得用Stream流?
舉個簡單的例子:
學(xué)生對象:
@Data
@AllArgsConstructor
public class Student {
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "年齡")
private Integer age;
@ApiModelProperty(value = "性別(1-男西疤,2-女)")
private Integer sex;
}
學(xué)生對象集合
public class StreamDemo {
public static void main(String[] args) {
// 測試數(shù)據(jù)
List<Student> studentList = Lists.newArrayList();
studentList.add(new Student("CodeCow", 18, 1));
studentList.add(new Student("小明", 30, 1));
studentList.add(new Student("小豬", 40, 2));
studentList.add(new Student("小狗狗", 50, 2));
}
}
假如烦粒,現(xiàn)有需求:篩選所有姓小的同學(xué),并且名字有三個字代赁,最后對結(jié)果進(jìn)行打印輸出
小編很幸運(yùn)扰她,曾見過這樣的SAO代碼,可謂 “猛龍過江”管跺,管你三七二十一义黎,上來先整幾個for循環(huán)再說禾进;
public static void main(String[] args) {
//第一步:找出姓小的同學(xué)豁跑,放在list1
List<Student> list1 = Lists.newArrayList();
for (Student student : studentList) {
if (student.getName().startsWith("小")) {
list1.add(student);
}
}
//第二步:找出名字有三個字的同學(xué),放在list2
List<Student> list2 = Lists.newArrayList();
for (Student student : list1) {
if (student.getName().length() == 3) {
list2.add(student);
}
}
//第三步:打印結(jié)果
for (Student student : list2) {
System.out.println(student);
}
}
接下來泻云,我們Debug運(yùn)行下艇拍,看下結(jié)果:
Student(name=小狗狗, age=50, sex=2)
臥CAO,學(xué)生倒是賽選出來了宠纯,但是卸夕,現(xiàn)在賽選 條件只有三個,當(dāng)條件有幾十個時婆瓜,那幾十個for循環(huán)快集,不累嗎,那可以說是非常酸爽了……
再者廉白,你將Java 8 的一哥——stream流个初,至于何地
[圖片上傳失敗...(image-f0a1c5-1596705940785)]
體驗(yàn)哈Stream流的更優(yōu)寫法
大家肯定都知道Lambda吧,Java 8的Lambda讓我們可以更加專注于做什么(What)猴蹂,而不是怎么做(How)
這點(diǎn)小編也在上篇文章《兩年了院溺,才知道如何實(shí)現(xiàn)多線程,哎 》中結(jié)合“線程 + 匿名內(nèi)部類” 進(jìn)行了對比說明磅轻。有空可以看下
現(xiàn)在珍逸,我們體會下Stream流的優(yōu)雅:
public static void main(String[] args) {
studentList.stream()
.filter(i -> i.getName().startsWith("小"))//過濾出姓小的同學(xué)
.filter(i -> i.getName().length() == 3) //過濾出名字有三個字的同學(xué)
.forEach(System.out::println); //打印結(jié)果
}
再次Debug運(yùn)行下,看下結(jié)果:
Student(name=小狗狗, age=50, sex=2)
不難發(fā)現(xiàn)聋溜,區(qū)區(qū)3行代碼谆膳,運(yùn)行結(jié)果也一樣;同時撮躁,順帶解決了上面的SAO操作摹量, 他不香嗎?
總結(jié)下,為什么很香
- 第一點(diǎn):可以清楚地知道我們要對一個數(shù)據(jù)集做何種操作缨称,可讀性賊強(qiáng)(就三行凝果,讀不明白 ?)
- 第二點(diǎn):可以很輕松地獲取并行化Stream流睦尽,不用自己編寫多線程代碼(阿牛上篇文章就是最好的證明F骶弧!)
- 第三點(diǎn):可以讓我們更加專注于業(yè)務(wù)邏輯 (還用考慮用幾個for循環(huán)嗎5狈病山害!)。
簡而言之沿量,Stream浪慌,愛了,愛了
您也為這就是Stream流的全部嗎朴则,“No权纤,No,No”
接下來乌妒,咋們看下Stream流 風(fēng)SAO 集合
了解下Stream流更多SAO操作
需求1:獲取姓小同學(xué)的集合
public static void main(String[] args) {
List<Student> list = studentList.stream()
.filter(i -> i.getName().startsWith("小"))
.collect(Collectors.toList());
}
結(jié)果為:
[
Student(name=小明, age=30, sex=1),
Student(name=小豬, age=40, sex=2),
Student(name=小狗狗, age=50, sex=2)
]
需求2:獲取姓小的同學(xué)汹想,并且年齡大于30的集合
public static void main(String[] args) {
List<Student> list = studentList.stream()
.filter(i -> i.getName().startsWith("小") && i.getAge() >30)
.collect(Collectors.toList());
}
結(jié)果為:
[
Student(name=小豬, age=40, sex=2),
Student(name=小狗狗, age=50, sex=2)
]
需求3:獲取姓名為“小明”的同學(xué),的集合
public static void main(String[] args) {
List<Student> list = studentList.stream()
.filter(i -> i.getName().equals("小明"))
.collect(Collectors.toList());
}
結(jié)果為:
[Student(name=小明, age=40, sex=1)]
需求4:獲取所有同學(xué)姓名的集合
public static void main(String[] args) {
List<String> list = studentList.stream()
.map(Student::getName)
.collect(Collectors.toList());
}
結(jié)果為:
[CodeCow, 小明, 小豬, 小狗狗]
需求5:根據(jù)學(xué)生年齡進(jìn)行升序排序
public static void main(String[] args) {
List<Student> list = studentList.stream()
.sorted(Comparator.comparing(Student::getAge))
.collect(Collectors.toList());
}
結(jié)果為:
[
Student(name=CodeCow, age=18, sex=1),
Student(name=小明, age=40, sex=1),
Student(name=小豬, age=50, sex=2),
Student(name=小狗狗, age=50, sex=2)
]
需求6:根據(jù)學(xué)生年齡進(jìn)行降序排序
public static void main(String[] args) {
List<Student> list = studentList.stream()
.sorted(Comparator.comparing(Student::getAge).reversed())
.collect(Collectors.toList());
}
結(jié)果為:
[
Student(name=小豬, age=50, sex=2),
Student(name=小狗狗, age=50, sex=2),
Student(name=小明, age=40, sex=1),
Student(name=CodeCow, age=18, sex=1)
]
需求7:distinct 去重
public static void main(String[] args) {
List<Integer> integers = Lists.list(30, 40, 10, 20, 20, 10, 50, 20);
List<Integer> collect =
integers.stream().distinct().collect(Collectors.toList());
System.out.println(collect);//[30, 40, 10, 20, 50] 去重結(jié)果
}
需求8:找最小值 min撤蚊,總數(shù)量 count
public static void main(String[] args) {
List<Integer> integers = Lists.list(30, 40, 10, 20, 20, 10, 50, 20);
Integer integer1 = integers.stream().min(Integer::compareTo).orElse(-1);
System.out.println(integer1); //10 最小值
long count = integers.stream().count();
System.out.println(count);//8 總數(shù)量
}
淺聊 Java 8 Stream 流古掏,今就到這,下文見 _
后記
好啦侦啸,今就先聊到這里吧槽唾,本文僅僅是 拋磚引玉 而已,使用了 Java 8 Stream流 和大家聊了聊光涂,打了個樣庞萍;且并非Stream流所有特性,這只是其 冰山一角顶捷;下文見
★★ 好文推薦 ★★
- 兩年了挂绰,才知道如何實(shí)現(xiàn)多線程 ,哎
- 答應(yīng)我服赎,別再if/else校驗(yàn)請求參數(shù)了可以嗎
- 淺聊過濾器 + 攔截器 + JWT
- 微信小程序支付 + 公眾號支付 (含源碼)
- 微信公眾號授權(quán)+獲取用戶信息+jwt登錄 (含源碼)
- 微信小程序授權(quán)+獲取用戶手機(jī)號+jwt登錄 (含源碼)
小聲BB
- 中國傳統(tǒng)文化葵蒂,先仔細(xì)看,若有用重虑,再點(diǎn)贊践付, 給自己一點(diǎn)思考的時間
- 更多幽默、風(fēng)趣好文缺厉,盡在“ CodeCow ” , WX搜索 CodeCow永高,可以看看
《 Java如海隧土,學(xué)習(xí)作舟,泛舟于海命爬,方知Java之寬闊 》