国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java 8 Stream實踐

JerryWangSAP / 1712人閱讀

摘要:前面的話中的于版本析出,平時項目中也有用到,今天就系統(tǒng)的來實踐一下。可以根據(jù)隊員的年齡進行分組執(zhí)行結(jié)果為費爾南多費爾南迪尼奧隋維杰克魯伊夫卡爾德克阿德里安結(jié)果是一個,為不重復(fù)的年齡,為屬于該年齡的隊員列表。已經(jīng)實現(xiàn)了分組。

前面的話】Java中的Stream于1.8版本析出,平時項目中也有用到,今天就系統(tǒng)的來實踐一下。下面借用重慶力帆隊伍中我個人比較喜歡的球員來操作一波,隊員的年齡為了便于展示某些api做了調(diào)整,請不要太認(rèn)真哦。

壹. Stream理解

在java中我們稱Stream為『』,我們經(jīng)常會用流去對集合進行一些流水線的操作。stream就像工廠一樣,只需要把集合、命令還有一些參數(shù)灌輸?shù)搅魉€中去,就可以加工成得出想要的結(jié)果。這樣的流水線能大大簡潔代碼,減少操作。給我個人的感覺類似JavaScript中的鏈?zhǔn)胶瘮?shù)。

貳. Stream流程
原集合 —> 流 —> 各種操作(過濾、分組、統(tǒng)計) —> 終端操作

Stream流的操作流程一般都是這樣的,先將集合轉(zhuǎn)為流,然后經(jīng)過各種操作,比如過濾、篩選、分組、計算。最后的終端操作,就是轉(zhuǎn)化成我們想要的數(shù)據(jù),這個數(shù)據(jù)的形式一般還是集合,有時也會按照需求輸出count計數(shù)。下文會一一舉例。

叁. API實踐

首先,定義一個用戶對象,包含姓名、年齡、id三個成員變量:

package com.eelve.training.entity;

import lombok.*;

import javax.persistence.*;

/**
 * @ClassName User
 * @Description TDO
 * @Author zhao.zhilue
 * @Date 2019/6/28 15:21
 * @Version 1.0
 **/
@Data
@Entity
@Table(name = "user")
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(exclude={"id","name"})
public class User implements  Comparable{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    /**
     * Link name.
     */
    @Column(name = "name", columnDefinition = "varchar(255) not null")
    private String name;

    @Column(name = "age")
    private Integer age;

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public int compareTo(User o) {
        return age.compareTo(o.getAge());
    }
}

然后在數(shù)據(jù)庫中插入測試數(shù)據(jù),見下圖:

3.1過濾 1)filter 過濾(T-> boolean)

假如我們要實現(xiàn)過濾出40歲以下的隊員,我們可以這樣來實現(xiàn):

@Test
    public void testUserStreamFilter(){
        List userList = userMapper.getALL();
        List resultList = userList.stream().filter(user -> user.getAge() <= 40).collect(Collectors.toList());
        for (User user :  resultList){
            System.out.println(user.toString());
        }
    }

filter里面,->箭頭后面跟著的是一個boolean值,可以寫任何的過濾條件,就相當(dāng)于sql中where后面的東西,換句話說,能用sql實現(xiàn)的功能這里都可以實現(xiàn)
執(zhí)行結(jié)果為:

User(id=1, name=費爾南多, age=25)
User(id=2, name=費爾南迪尼奧, age=26)
User(id=3, name=卡爾德克, age=27)
User(id=4, name=阿德里安, age=28)
User(id=5, name=隋維杰, age=26)
2)distinct 去重

其用法和sql中的使用類似,假如我們要實現(xiàn)過去除用重復(fù)年齡的隊員,我們可以這樣來實現(xiàn):

@Test
    public void testUserDistinct(){
        List userList = userMapper.getALL();
        List resultList = userList.stream().distinct().collect(Collectors.toList());
        for (User user :  resultList){
            System.out.println(user.toString());
        }
    }

執(zhí)行結(jié)果為:

User(id=1, name=費爾南多, age=25)
User(id=2, name=費爾南迪尼奧, age=26)
User(id=3, name=卡爾德克, age=27)
User(id=4, name=阿德里安, age=28)
User(id=6, name=克魯伊夫, age=43)
3)sorted排序

如果流中的元素的類實現(xiàn)了 Comparable 接口,即有自己的排序規(guī)則,那么可以直接調(diào)用 sorted() 方法對元素進行排序,如:

 @Override
    public int compareTo(User o) {
        return age.compareTo(o.getAge());
    }
@Test
    public void testUserStreamSorted(){
        List userList = userMapper.getALL();
        List resultList = userList.stream().sorted().collect(Collectors.toList());
        for (User user :  resultList){
            System.out.println(user.toString());
        }
    }

反之, 需要調(diào)用 sorted((T, T) -> int) 實現(xiàn) Comparator 接口。

@Test
    public void testUserStreamSortedWithComparator(){
        List userList = userMapper.getALL();
        List resultList = userList.stream().sorted(Comparator.comparingInt(User::getAge)).collect(Collectors.toList());
        for (User user :  resultList){
            System.out.println(user.toString());
        }
    }

執(zhí)行結(jié)果為:

User(id=1, name=費爾南多, age=25)
User(id=2, name=費爾南迪尼奧, age=26)
User(id=5, name=隋維杰, age=26)
User(id=3, name=卡爾德克, age=27)
User(id=4, name=阿德里安, age=28)
User(id=6, name=克魯伊夫, age=43)
4)limit() 返回前n個元素

如果想知道隊伍中年齡最小的就可以使用下面來實現(xiàn):

@Test
    public void testUserStreamLimit(){
        List userList = userMapper.getALL();
        List resultList = userList.stream().limit(2).collect(Collectors.toList());
        for (User user :  resultList){
            System.out.println(user.toString());
        }
    }

執(zhí)行結(jié)果為:

User(id=1, name=費爾南多, age=25)
User(id=2, name=費爾南迪尼奧, age=26)
5)skip

它的用法和limit正好相反,是去除前面幾個元素。
假如我們要去除前面兩個元素就可以使用下面的方法來實現(xiàn):

@Test
    public void testUserStreamSkip(){
        List userList = userMapper.getALL();
        List resultList = userList.stream().skip(2).collect(Collectors.toList());
        for (User user :  resultList){
            System.out.println(user.toString());
        }
    }

執(zhí)行結(jié)果為:

User(id=3, name=卡爾德克, age=27)
User(id=4, name=阿德里安, age=28)
User(id=5, name=隋維杰, age=26)
User(id=6, name=克魯伊夫, age=43)
6)組合使用

以上的過濾函數(shù)物品們可以組合來使用來實現(xiàn)我們具體的需求,示例代碼如下:

 @Test
    public void testUserStreamSortLimit(){
        List userList = userMapper.getALL();
        List resultList = userList.stream().sorted().limit(5).collect(Collectors.toList());
        for (User user :  resultList){
            System.out.println(user.toString());
        }
    }

這樣我們就可以得到先排序后限制的結(jié)果:

User(id=1, name=費爾南多, age=25)
User(id=2, name=費爾南迪尼奧, age=26)
User(id=5, name=隋維杰, age=26)
User(id=3, name=卡爾德克, age=27)
User(id=4, name=阿德里安, age=28)
3.2 映射 1)map(T->R)

map是將T類型的數(shù)據(jù)轉(zhuǎn)為R類型的數(shù)據(jù),比如我們想要設(shè)置一個新的list,存儲用戶所有的城市信息。

@Test
    public void testUserStreamMap(){
        List userList = userMapper.getALL();
        List resultList = userList.stream().map(User::getAge).distinct().collect(Collectors.toList());
        System.out.println(resultList.toString());
    }

這樣我們可以得到所有年齡的樣本,執(zhí)行結(jié)果為:

[25, 26, 27, 28, 43]
2)flatMap(T -> Stream)

將流中的每一個元素 T 映射為一個流,再把每一個流連接成為一個流。

@Test
    public void testStreamMap(){
        List habitsList = new ArrayList<>();
        habitsList.add("唱歌,聽歌");
        habitsList.add("羽毛球,足球,登山");
        habitsList = habitsList.stream().map(s -> s.split(",")).flatMap(Arrays::stream).collect(Collectors.toList());
        System.out.println(habitsList);
    }

執(zhí)行結(jié)果為:

[唱歌, 聽歌, 羽毛球, 足球, 登山]

這里原集合中的數(shù)據(jù)由逗號分割,使用split進行拆分后,得到的是Stream,字符串?dāng)?shù)組組成的流,要使用flatMap的Arrays::stream,將Stream轉(zhuǎn)為Stream,然后把流相連接,組成了完整的唱歌, 聽歌, 羽毛球, 足球, 登山。

3.3 查找 1)allMatch(T->boolean)

檢測是否全部滿足參數(shù)行為,假如我們要檢測是不是所有隊員都是U21的球員:

@Test
    public void testUserStreamAllMatch(){
        List userList = userMapper.getALL();
        boolean isNotU21 = userList.stream().allMatch(user -> user.getAge() >= 21);
        System.out.println("是否都不是U21球員:" + isNotU21);
    }

執(zhí)行結(jié)果為:

是否都不是U21球員:true
2)anyMatch(T->boolean)

檢測是否有任意元素滿足給定的條件,比如,想知道是否有26歲的球員:

@Test
    public void testUserStreamAnyMatch(){
        List userList = userMapper.getALL();
        boolean isAgeU26 = userList.stream().anyMatch(user -> user.getAge() == 26);
        System.out.println("是否有26歲的球員:" + isAgeU26);
    }

執(zhí)行結(jié)果為:

是否有26歲的球員:true
3)noneMatch(T -> boolean)

流中是否有元素匹配給定的 T -> boolean 條件。比如我們要檢測是否含有U18的隊員:

 @Test
    public void testUserStreamNoneMatch(){
        List userList = userMapper.getALL();
        boolean isNotU18 = userList.stream().noneMatch(user -> user.getAge() <= 18);
        System.out.println("是否都不是U18球員:" + isNotU18);
    }

執(zhí)行結(jié)果為:

是否都不是U18球員:true

說明沒有U18的隊員。

4)findFirst( ):找到第一個元素
@Test
    public void testUserFindFirst(){
        List userList = userMapper.getALL();
        Optional firstUser = userList.stream().sorted().findFirst();
        System.out.println(firstUser.toString());
    }

執(zhí)行結(jié)果為:

Optional[User(id=1, name=費爾南多, age=25)]
5)findAny():找到任意一個元素
@Test
    public void testUserFindAny(){
        List userList = userMapper.getALL();
        Optional anytUser = userList.parallelStream().sorted().findAny();
        System.out.println(anytUser.toString());
    }

執(zhí)行結(jié)果為:

Optional[User(id=2, name=費爾南迪尼奧, age=26)]
3.4 歸納計算 1)求隊員的總?cè)藬?shù)
@Test
    public void testUserCount(){
        List userList = userMapper.getALL();
        long totalAge = userList.stream().collect(Collectors.counting());
        System.out.println("隊員人數(shù)為:" + totalAge);
    }

執(zhí)行結(jié)果為:

隊員人數(shù)為:6
2)得到某一屬性的最大最小值
@Test
    public void testUserMaxAndMin(){
        List userList = userMapper.getALL();
        Optional userMaxAge = userList.stream().collect(Collectors.maxBy(Comparator.comparing(User::getAge)));
        System.out.println("年齡最大的隊員為:" + userMaxAge.toString());

        Optional userMinAge = userList.stream().collect(Collectors.minBy(Comparator.comparing(User::getAge)));
        System.out.println("年齡最小的隊員為:" + userMinAge.toString());
    }

執(zhí)行結(jié)果為:

年齡最大的隊員為:Optional[User(id=6, name=克魯伊夫, age=43)]
年齡最小的隊員為:Optional[User(id=1, name=費爾南多, age=25)]
3)求年齡總和是多少
@Test
    public void testUserSummingInt(){
        List userList = userMapper.getALL();
        int totalAge = userList.stream().collect(Collectors.summingInt(User::getAge));
        System.out.println("年齡總和為:" + totalAge);
    }

執(zhí)行結(jié)果為:

年齡總和為:175

我們經(jīng)常會用BigDecimal來記錄金錢,假設(shè)想得到BigDecimal的總和:
// 獲得列表對象金額, 使用reduce聚合函數(shù),實現(xiàn)累加器
BigDecimal sum = myList.stream() .map(User::getMoney)
.reduce(BigDecimal.ZERO,BigDecimal::add);

4)求年齡平均值
@Test
    public void testUserAveragingInt(){
        List userList = userMapper.getALL();
        Double totalAge = userList.stream().collect(Collectors.averagingInt(User::getAge));
        System.out.println("平均年齡為:" + totalAge);
    }

執(zhí)行結(jié)果為:

平均年齡為:29.166666666666668
5)一次性得到元素的個數(shù)、總和、最大值、最小值
@Test
    public void testUserSummarizingInt(){
        List userList = userMapper.getALL();
        IntSummaryStatistics  statistics  = userList.stream().collect(Collectors.summarizingInt(User::getAge));
        System.out.println("年齡的統(tǒng)計結(jié)果為:" + statistics );
    }

執(zhí)行結(jié)果為:

年齡的統(tǒng)計結(jié)果為:IntSummaryStatistics{count=6, sum=175, min=25, average=29.166667, max=43}
6)字符串拼接

要將隊員的姓名連成一個字符串并用逗號分割。

@Test
    public void testUserJoining(){
        List userList = userMapper.getALL();
        String  name  = userList.stream().map(User::getName).collect(Collectors.joining(","));
        System.out.println("所有的隊員名字:" + name );
    }

執(zhí)行結(jié)果為:

所有的隊員名字:費爾南多,費爾南迪尼奧,卡爾德克,阿德里安,隋維杰,克魯伊夫
3.5 分組

在數(shù)據(jù)庫操作中,我們經(jīng)常通過GROUP BY關(guān)鍵字對查詢到的數(shù)據(jù)進行分組,java8的流式處理也提供了分組的功能。使用Collectors.groupingBy來進行分組。

1)可以根據(jù)隊員的年齡進行分組
 @Test
    public void testUserGroupingBy(){
        List userList = userMapper.getALL();
        Map> ageMap  = userList.stream().collect(Collectors.groupingBy(User::getAge));
        for (Map.Entry> entry :ageMap.entrySet()){
            System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
        }
    }

執(zhí)行結(jié)果為:

key= 25 and value= [User(id=1, name=費爾南多, age=25)]
key= 26 and value= [User(id=2, name=費爾南迪尼奧, age=26), User(id=5, name=隋維杰, age=26)]
key= 43 and value= [User(id=6, name=克魯伊夫, age=43)]
key= 27 and value= [User(id=3, name=卡爾德克, age=27)]
key= 28 and value= [User(id=4, name=阿德里安, age=28)]

結(jié)果是一個map,key為不重復(fù)的年齡,value為屬于該年齡的隊員列表。已經(jīng)實現(xiàn)了分組。另外我們還可以繼續(xù)分組得到兩次分組的結(jié)果。

2)如果僅僅想統(tǒng)計各年齡的隊員個數(shù)是多少,并不需要對應(yīng)的list

按年齡分組并統(tǒng)計人數(shù):

@Test
    public void testUserGroupingByCount(){
        List userList = userMapper.getALL();
        Map ageMap  = userList.stream().collect(Collectors.groupingBy(User::getAge,Collectors.counting()));
        for (Map.Entry entry :ageMap.entrySet()){
            System.out.println("隊員中" + entry.getKey() + "歲的隊員人數(shù)為:" + entry.getValue());
        }
    }

執(zhí)行結(jié)果為:

隊員中25歲的隊員人數(shù)為:1
隊員中26歲的隊員人數(shù)為:2
隊員中43歲的隊員人數(shù)為:1
隊員中27歲的隊員人數(shù)為:1
隊員中28歲的隊員人數(shù)為:1
3)partitioningBy 分區(qū)

分區(qū)與分組的區(qū)別在于,分區(qū)是按照 true 和 false 來分的,因此partitioningBy 接受的參數(shù)的 lambda 也是 T -> boolean

@Test
    public void testUserPartitioningBy (){
        List userList = userMapper.getALL();
        Map> partitioningByMap  = userList.stream().collect(partitioningBy(user -> user.getAge() >= 30));
        for (Map.Entry> entry :partitioningByMap.entrySet()){
            System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
        }
    }

執(zhí)行結(jié)果為:

key= false and value= [User(id=1, name=費爾南多, age=25), User(id=2, name=費爾南迪尼奧, age=26), User(id=3, name=卡爾德克, age=27), User(id=4, name=阿德里安, age=28), User(id=5, name=隋維杰, age=26)]
key= true and value= [User(id=6, name=克魯伊夫, age=43)]

寫在后面的話】留下stream的類實現(xiàn)的方法和依賴圖,前面的實踐也只是挑選了幾個比較常用的Api。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/76086.html

相關(guān)文章

  • Java 8怎么了:局部套用vs閉包

    摘要:本文主要介紹了中的閉包與局部套用功能,由國內(nèi)管理平臺編譯呈現(xiàn)。譬如,認(rèn)為給帶來了閉包特性就是其中之一。但是首先,我們將考慮如何利用閉包進行實現(xiàn)。很顯然,閉包打破了這一準(zhǔn)則。這就是局部調(diào)用,它總是比閉包更為穩(wěn)妥。 【編者按】本文作者為專注于自然語言處理多年的 Pierre-Yves Saumont,Pierre-Yves 著有30多本主講 Java 軟件開發(fā)的書籍,自2008開始供職于 ...

    3fuyu 評論0 收藏0
  • Java編程方法論:響應(yīng)式RxJava與代碼設(shè)計實戰(zhàn)》序

    摘要:原文鏈接編程方法論響應(yīng)式與代碼設(shè)計實戰(zhàn)序,來自于微信公眾號次靈均閣正文內(nèi)容在一月的架構(gòu)和設(shè)計趨勢報告中,響應(yīng)式編程和函數(shù)式仍舊編列在第一季度的早期采納者中。 原文鏈接:《Java編程方法論:響應(yīng)式RxJava與代碼設(shè)計實戰(zhàn)》序,來自于微信公眾號:次靈均閣 正文內(nèi)容 在《2019 一月的InfoQ 架構(gòu)和設(shè)計趨勢報告》1中,響應(yīng)式編程(Reactive Programming)和函數(shù)式...

    PAMPANG 評論0 收藏0
  • [譯] Java 中最常見的 5 個錯誤

    摘要:近日,在上列舉了開發(fā)中常見的個錯誤,與君共免。在多線程中并發(fā)修改集合內(nèi)容是非常常見的,因此需要使用并發(fā)編程中常用的方法進行處理,例如同步鎖對于并發(fā)修改采用特殊的集合等等。在單線程和多線程情況下解決這個問題有微小的差別。 在編程時,開發(fā)者經(jīng)常會遭遇各式各樣莫名錯誤。近日,Sushil Das 在 Geek On Java上列舉了 Java 開發(fā)中常見的 5 個錯誤,與君共「免」。 原文...

    chemzqm 評論0 收藏0
  • Java8新特性總覽

    摘要:新特性總覽標(biāo)簽本文主要介紹的新特性,包括表達式方法引用流默認(rèn)方法組合式異步編程新的時間,等等各個方面。還有對應(yīng)的和類型的函數(shù)連接字符串廣義的歸約匯總起始值,映射方法,二元結(jié)合二元結(jié)合。使用并行流時要注意避免共享可變狀態(tài)。 Java8新特性總覽 標(biāo)簽: java [TOC] 本文主要介紹 Java 8 的新特性,包括 Lambda 表達式、方法引用、流(Stream API)、默認(rèn)方...

    mayaohua 評論0 收藏0
  • Java 8函數(shù)式編程》作者Richard Warbourton:Java的亮點不是語言本身

    摘要:根據(jù)對社區(qū)和新特性的深刻理解,他創(chuàng)作了函數(shù)式編程一書。問你在倫敦社區(qū)的經(jīng)歷是否幫助你創(chuàng)作了函數(shù)式編程這本書絕對是這樣。我認(rèn)為引入函數(shù)式編程會為很多編程任務(wù)提供方便。問之前的是面向?qū)ο蟮模F(xiàn)在全面支持函數(shù)式編程。 非商業(yè)轉(zhuǎn)載請注明作譯者、出處,并保留本文的原始鏈接:http://www.ituring.com.cn/article/199271 Richard Warburto...

    mzlogin 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<