每日一例 | 今天繼續(xù)效率之王……

昨天我們講了stream的一些常用操作,從實際意義上來說,確實可以極大提高我們的代碼效率和整潔程度,今天我們來繼續(xù)看。
補(bǔ)充知識
首先,先要補(bǔ)充一點,stream生成map的時候,key是不能重復(fù)的,如果你的key重復(fù)了會報錯的:
List<String> stringList = Lists.newArrayList("test1", "test2", "test3", "test1");
Map<String, String> collect = stringList.stream().collect(Collectors.toMap(s -> s, s -> s));
運(yùn)行上面的代碼會報錯,因為上面的list包含了兩個test1:
根據(jù)錯誤提示信息,說明錯誤的原因是key重復(fù)了,針對這種情況,或者說在你不確定key是否重復(fù)的情況下,可以在toMap這里增加一個表達(dá)式,避免異常出現(xiàn):
Map<String, String> collect2 = stringList.stream().collect(Collectors.toMap(s -> s, s -> s, (a, b) -> a));
最后面表達(dá)式的意思是,如果key重復(fù)了保留第一個key對應(yīng)的value,也就是這里a,如果你要保留后一個key對應(yīng)的value,改成(a, b) -> b即可。
其他常用方法
現(xiàn)在我們開始補(bǔ)充昨天沒有說完的其他常用方法。
map
map方法也是stream的一個核心方法,返回Stream

這個方法是一個通用的處理方法,你可以通過map處理你的數(shù)據(jù),比如我們想把上面的stringList處理成大寫的list,我們可以在map方法內(nèi)部直接處理:
List<String> stringList = Lists.newArrayList("test1", "test2", "test3", "test1");
List<String> collect1 = stringList.stream().map(s -> s.toUpperCase()).collect(Collectors.toList());
// 當(dāng)然也可以寫成這樣:
List<String> collect2 = stringList.stream().map(String :: toUpperCase).collect(Collectors.toList());
或者你想統(tǒng)計stringList中的字符長度,并生成新的list:
List<Integer> collect6 = stringList.stream().map(String::length).collect(Collectors.toList());
當(dāng)然你說,上面的這種用法,不通過map能不能實現(xiàn)?當(dāng)然能,但對toList/toSet是不行的,對toMap是可以的:
Map<String, String> collect3 = stringList.stream().collect(Collectors.toMap(s -> s.toUpperCase(), s -> s, (a, b) -> a));
Map<String, String> collect3 = stringList.stream().map(String :: toUpperCase).collect(Collectors.toMap(s -> s, s -> s, (a, b) -> a));
distinct
經(jīng)常寫sql的小伙伴肯定對這個關(guān)鍵字很熟悉,作用就是去重,在這里也一樣,是不是有些強(qiáng)大,我們先來試一下:
List<String> stringList = Lists.newArrayList("test1", "test2", "test3", "test1");
List<String> collect = stringList.stream().distinct().collect(Collectors.toList());
輸出結(jié)果:

重復(fù)數(shù)據(jù)確實已經(jīng)被移除了,經(jīng)過我的實驗,它也可以對實體類的集合進(jìn)行去重:
TestEntity testEntity = new TestEntity();
testEntity.setAge(1231);
testEntity.setId(124143545L);
testEntity.setName("阿波羅");
ChildEntriy childEntriy = new ChildEntriy();
childEntriy.setId(15252L);
childEntriy.setName("apollo");
testEntity.setChildEntriy(childEntriy);
ArrayList<TestEntity> testEntities = Lists.newArrayList(testEntity, testEntity);
System.out.println(testEntities);
List<TestEntity> collect8 = testEntities.stream().distinct().collect(Collectors.toList());
System.out.println(collect8);
打印結(jié)果:

sorted
顧名思義就是排序,而且排序的算法是可以靈活選擇的:
ArrayList<String> strings = Lists.newArrayList("w", "b", "d", "l", "o", "g");
System.out.println(strings);
List<String> collect9 = strings.stream().sorted().collect(Collectors.toList());
System.out.println(collect9);
List<String> collect10 = strings.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
System.out.println(collect10);
輸出結(jié)果:

最后面的是反序,其他排序方式可以自己選擇:

總結(jié)
當(dāng)然還有很多其他的方法沒有說到,但是上面這些日常工作中如果能用到,那已經(jīng)很優(yōu)秀了,而且你寫代碼的效率也會極大提高,當(dāng)然更多的東西你還是要靠自己去學(xué)習(xí),畢竟stream作為一個核心特性之一,方法太多了,不可能面面俱到。以前對stream不了解的時候,確實也意識不到它優(yōu)秀之處,但是最近一段時間的使用之后,發(fā)現(xiàn)函數(shù)式編程真的美,再也不用寫繁瑣的無用代碼了。最后,我想說,真香!
項目路徑:
https://github.com/Syske/example-everyday
本項目會每日更新,讓我們一起學(xué)習(xí),一起進(jìn)步,遇見更好的自己,加油呀
- END -