亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java?stream使用指南之sorted使用及進階方式

 更新時間:2024年05月11日 09:05:54   作者:阿亮_1024  
這篇文章主要介紹了java?stream使用指南之sorted使用及進階方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

引入

用了一段時間的jdk8的新特性,lambda表達式、方法引用、stream流,用起來是真的順手啊,最近碰到了一個排序的問題,引發(fā)了一些思考,然后就寫了這篇博客,歸納總結(jié)sorted的用法,在做筆記的同時也讓自己有更深的理解。

數(shù)據(jù)準備

1. 依賴

我喜歡用google的集合工具類,讓我構(gòu)造測試數(shù)據(jù)更簡便。

然后也用lombok,依賴:

        <!--google集合工具類-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.0-jre</version>
        </dependency>

			<!--lombok,需要插件配合使用-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>

2. 相關(guān)類

User類

/*
*鏈式調(diào)用,我也有寫相關(guān)博客,不過不是介紹基礎(chǔ)用法的,是這個鏈式調(diào)用一個不太完美的地方,
*感興趣的可以去看一看:https://blog.csdn.net/ql_7256/article/details/120274432 
*/
@Data
@Accessors(chain = true) 
public class User  {

    private String username;
    private String password;
    private Integer age;
    private Integer height;

    private Address address;

    private Map others;

}

Address類,注意:這個類在后續(xù)的測試中要改動

@Data
@Accessors(chain = true)
public class Address {

    private String province;
    private String city;
    private String county;
    
}

數(shù)據(jù)準備,

    private List<User> users = new ArrayList<User>() {{
        add(new User().setUsername("張三").setPassword("123456").setAge(20).setHeight(170)
                .setAddress(new Address().setProvince("四川省").setCity("成都市").setCounty("武侯區(qū)"))
                .setOthers(ImmutableMap.builder().put("sorted","AAA").put("bbb","BBB").put("ccc","CCC").build()));

        add(new User().setUsername("李四").setPassword("123456").setAge(16).setHeight(175)
                .setAddress(new Address().setProvince("四川省").setCity("成都市").setCounty("錦江區(qū)"))
                .setOthers(ImmutableMap.builder().put("sorted","DDD").put("eee","EEE").put("fff","FFF").build()));

        add(new User().setUsername("王五").setPassword("123456").setAge(20).setHeight(180)
                .setAddress(new Address().setProvince("四川省").setCity("成都市").setCounty("青羊區(qū)"))
                .setOthers(ImmutableMap.builder().put("sorted","GGG").put("hhh","HHH").put("iii","III").build()));

        add(new User().setUsername("趙六").setPassword("123456").setAge(17).setHeight(168)
                .setAddress(new Address().setProvince("四川省").setCity("成都市").setCounty("高新區(qū)"))
                .setOthers(ImmutableMap.builder().put("sorted","JJJ").put("kkk","KKK").put("lll","LLL").build()));
    }};


    private List<String> strings = new ArrayList<String>() {{
        add("222");add("666");add("444");add("111");add("333");add("555");
    }};

    private List<Integer> integers = new ArrayList<Integer>() {{
        add(222);add(555);add(666);;add(333);add(444);add(111);
    }};

    private List others = new ArrayList() {{
        add(444);add(555);add(666);add(111);add(222);add(333);
    }};

初體驗

stream流、方法引用、lambda那些前置知識咱們就不說了哈,直接上手,先體直觀的驗一下排序

        List<String> sortedStrings = strings.stream().sorted().collect(Collectors.toList());
        
        // [111, 222, 333, 444, 555, 666]
        System.out.println(sortedStrings);

        
        
        List<User> sortedUsers = users.stream().sorted(Comparator.comparing(e -> e.getAge())).collect(Collectors.toList());
        // 等效寫法如下
        // List<User> sortedUsers = users.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());
        
        // [User(username=李四, password=123456, age=16, height=175, address=Address(province=四川省, city=成都市, county=錦江區(qū)), others={sorted=DDD, eee=EEE, fff=FFF}), User(username=趙六, password=123456, age=17, height=168, address=Address(province=四川省, city=成都市, county=高新區(qū)), others={sorted=JJJ, kkk=KKK, lll=LLL}), User(username=張三, password=123456, age=20, height=170, address=Address(province=四川省, city=成都市, county=武侯區(qū)), others={sorted=AAA, bbb=BBB, ccc=CCC}), User(username=王五, password=123456, age=20, height=180, address=Address(province=四川省, city=成都市, county=青羊區(qū)), others={sorted=GGG, hhh=HHH, iii=III})]
        System.out.println(sortedUsers);

很簡單,也沒啥難理解的,就是排序

基礎(chǔ)用法

排序的初體驗之后,我們來看看幾種正式場景下的使用

1. 降序幾種方式

在上面的體驗排序中,排序的結(jié)果默認都是升序的,那如果我要降序呢?那怎么辦?有三種方式,或者三種寫法

1. 使用reversed

根據(jù)user中的age降序

        List<User> collect = users.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());
        // [User(username=張三, password=123456, age=20, height=170, address=Address(province=四川省, city=成都市, county=武侯區(qū)), others={sorted=AAA, bbb=BBB, ccc=CCC}), User(username=王五, password=123456, age=20, height=180, address=Address(province=四川省, city=成都市, county=青羊區(qū)), others={sorted=GGG, hhh=HHH, iii=III}), User(username=趙六, password=123456, age=17, height=168, address=Address(province=四川省, city=成都市, county=高新區(qū)), others={sorted=JJJ, kkk=KKK, lll=LLL}), User(username=李四, password=123456, age=16, height=175, address=Address(province=四川省, city=成都市, county=錦江區(qū)), others={sorted=DDD, eee=EEE, fff=FFF})]
        System.out.println(collect);

根據(jù)User中age先排序,默認情況下是升序,然后再逆序一下,就變成了降序。但是這樣有點不好,因為是先排序然后在逆序的,要兩步操作。

2.使用Comparator.reverseOrder

根據(jù)user中的age降序

        List<User> collect1 = users.stream().sorted(Comparator.comparing(User::getAge, Comparator.reverseOrder())).collect(Collectors.toList());
        // [User(username=張三, password=123456, age=20, height=170, address=Address(province=四川省, city=成都市, county=武侯區(qū)), others={sorted=AAA, bbb=BBB, ccc=CCC}), User(username=王五, password=123456, age=20, height=180, address=Address(province=四川省, city=成都市, county=青羊區(qū)), others={sorted=GGG, hhh=HHH, iii=III}), User(username=趙六, password=123456, age=17, height=168, address=Address(province=四川省, city=成都市, county=高新區(qū)), others={sorted=JJJ, kkk=KKK, lll=LLL}), User(username=李四, password=123456, age=16, height=175, address=Address(province=四川省, city=成都市, county=錦江區(qū)), others={sorted=DDD, eee=EEE, fff=FFF})]
        System.out.println(collect1);

這種方式原理和和方法1差不多,只是寫法不一樣

3. 在sorted中使用compareTo

方式1和方式2都是利用sorted默認序,然后再逆序來實現(xiàn)排序的,這樣會有兩個步驟,先升序,然后再逆序。難道就沒有直接按照降序來排序的方法?肯定是有的。既然是排序,肯定是可以指定規(guī)則的

  • 按照年齡降序
        List<User> collect2 = users.stream().sorted((x, y) -> y.getAge().compareTo(x.getAge())).collect(Collectors.toList());
        // [User(username=張三, password=123456, age=20, height=170, address=Address(province=四川省, city=成都市, county=武侯區(qū)), others={sorted=AAA, bbb=BBB, ccc=CCC}), User(username=王五, password=123456, age=20, height=180, address=Address(province=四川省, city=成都市, county=青羊區(qū)), others={sorted=GGG, hhh=HHH, iii=III}), User(username=趙六, password=123456, age=17, height=168, address=Address(province=四川省, city=成都市, county=高新區(qū)), others={sorted=JJJ, kkk=KKK, lll=LLL}), User(username=李四, password=123456, age=16, height=175, address=Address(province=四川省, city=成都市, county=錦江區(qū)), others={sorted=DDD, eee=EEE, fff=FFF})]
        System.out.println(collect2);

這種方式是通過Integer中的compareTo方法來實現(xiàn)降序的,當(dāng)然也可以自己實現(xiàn),只不過age是Integer類型,既然Integer中已經(jīng)實現(xiàn)兩個Integer比較的方法,就可以偷個懶

4. 在sorted自定義規(guī)則

        List<User> collect3 = users.stream().sorted((x, y) -> y.getAge() - x.getAge()).collect(Collectors.toList());
        // [User(username=張三, password=123456, age=20, height=170, address=Address(province=四川省, city=成都市, county=武侯區(qū)), others={sorted=AAA, bbb=BBB, ccc=CCC}), User(username=王五, password=123456, age=20, height=180, address=Address(province=四川省, city=成都市, county=青羊區(qū)), others={sorted=GGG, hhh=HHH, iii=III}), User(username=趙六, password=123456, age=17, height=168, address=Address(province=四川省, city=成都市, county=高新區(qū)), others={sorted=JJJ, kkk=KKK, lll=LLL}), User(username=李四, password=123456, age=16, height=175, address=Address(province=四川省, city=成都市, county=錦江區(qū)), others={sorted=DDD, eee=EEE, fff=FFF})]
        System.out.println(collect3);

比較實際的最終結(jié)果就是返回一個數(shù)字,大于0、小于0、等于0,分別就代表大于、小于、等于,所以在sorted方法中返回一個做減法的數(shù)字即可。

2. 多級排序

比如我現(xiàn)在的需求是先按照年齡降序,年齡相同的再按照名字降序

List<User> collect = users.stream().sorted(Comparator.comparing(User::getAge, Comparator.reverseOrder()).thenComparing(User::getHeight, Comparator.reverseOrder())).collect(Collectors.toList());
 // [User(username=王五, password=123456, age=20, height=180, address=Address(province=四川省, city=成都市, county=青羊區(qū)), others={sorted=GGG, hhh=HHH, iii=III}), User(username=張三, password=123456, age=20, height=170, address=Address(province=四川省, city=成都市, county=武侯區(qū)), others={sorted=AAA, bbb=BBB, ccc=CCC}), User(username=趙六, password=123456, age=17, height=168, address=Address(province=四川省, city=成都市, county=高新區(qū)), others={sorted=JJJ, kkk=KKK, lll=LLL}), User(username=李四, password=123456, age=16, height=175, address=Address(province=四川省, city=成都市, county=錦江區(qū)), others={sorted=DDD, eee=EEE, fff=FFF})]
System.out.println(collect);

thenComparing顧名思義,再比較

進階

放在以前,我肯定會從stream 排序的api說起,看看有哪些方法,再看怎么調(diào)用,但是這流式太過抽象,所以我先講了怎么用,再回頭來看看有哪些api,本質(zhì)是什么

1. 本質(zhì)

在java.util.stream.Stream中,sorted方法有兩個重載形式

sorted

一個是無參,一個是需要一個參數(shù)java.util.Comparator。

1. Stream sorted();

其實這兩個方法我們都用過,在初體驗中,第一個就是無參的,這樣會根據(jù)默認規(guī)則排序,至于默認規(guī)則是什么,就是排序?qū)ο髮崿F(xiàn)的java.lang.Comparable接口中的compareTo方法,不然你試試跑一下這個

List<User> collect = users.stream().sorted().collect(Collectors.toList());

直接報錯,報錯的原因就是,你要排序一堆User,但是sorted這個無參的方法不知道排序的規(guī)則是什么。所以,在使用這個無參的方法時,被排序的元素必須得實現(xiàn)java.lang.Comparable接口,來指定排序規(guī)則。

2. Stream sorted(Comparator<? super T> comparator);

除了初體驗中的第一個排序,其他的全都是使用的這個方法,很神奇是吧?我好像傳的參數(shù)不止這樣。

但事實上就是這樣子,只傳了這個一個參數(shù),無非有兩種傳參形式:一種是確確實實的傳了一個java.util.Comparator進去,另外一種是自己實現(xiàn)了java.util.Comparator中的抽象方法compare,這個方法用來進行元素間的比較。因為java.util.Comparator是一個函數(shù)式接口,接口中只有compare這一個抽象方法,所以可以結(jié)合lambda表達式使用。

我們使用的.sorted(Comparator.comparing(……))其實就是直接傳了一個Comparator進去,因為Comparator.comparing這個方法:java.util.Comparator#comparing(java.util.function.Function<? super T,? extends U>, java.util.Comparator<? super U>) 返回的就是一個Comparator。

而類似這種使用:sorted((x, y) -> y.getAge().compareTo(x.getAge()))或者sorted((x, y) -> y.getAge() - x.getAge()),其實就是我們自己在實現(xiàn)java.util.Comparator中的抽象方法compare,這其實就是匿名內(nèi)部類---->簡化---->lambda表達式的這么一個過程,其實還可以簡化成 方法引用。

2. 拓展及思考

List<User> sortedUsers = users.stream().sorted(Comparator.comparing(x -> x.getOthers().get("aaa").toString())).collect(Collectors.toList());
List<User> sortedUsers2 = users.stream().sorted(Comparator.comparing(x -> x.getOthers().get("aaa").toString()).reversed()).collect(Collectors.toList());

為什么第二個排序會有問題?

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。 

相關(guān)文章

  • 自定義spring mvc的json視圖實現(xiàn)思路解析

    自定義spring mvc的json視圖實現(xiàn)思路解析

    這篇文章主要介紹了自定義spring mvc的json視圖的實現(xiàn)思路解析,本文給大家介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下
    2017-12-12
  • 如何使用SpringBoot集成Kafka實現(xiàn)用戶數(shù)據(jù)變更后發(fā)送消息

    如何使用SpringBoot集成Kafka實現(xiàn)用戶數(shù)據(jù)變更后發(fā)送消息

    Spring Boot集成Kafka實現(xiàn)用戶數(shù)據(jù)變更后,向其他廠商發(fā)送消息,我們需要考慮配置Kafka連接、創(chuàng)建Kafka Producer發(fā)送消息、監(jiān)聽用戶數(shù)據(jù)變更事件,并將事件轉(zhuǎn)發(fā)到Kafka,本文分步驟給大家講解使用SpringBoot集成Kafka實現(xiàn)用戶數(shù)據(jù)變更后發(fā)送消息,感興趣的朋友一起看看吧
    2024-07-07
  • SpringBoot整合redis使用緩存注解詳解

    SpringBoot整合redis使用緩存注解詳解

    這篇文章主要介紹了SpringBoot整合redis使用緩存注解詳解,@Cacheable在方法執(zhí)行前判斷對應(yīng)緩存是否存在,如果存在直接返回緩存結(jié)果,否者執(zhí)行方法將結(jié)果緩存,適用于查詢類,需要的朋友可以參考下
    2024-01-01
  • java 遍歷MAP的幾種方法示例代碼

    java 遍歷MAP的幾種方法示例代碼

    本文主要介紹java 遍歷MAP的知識資料,這里整理幾種方法及實現(xiàn)示例代碼,有興趣的小伙伴可以參考下
    2016-09-09
  • 基于Spring概念模型:PathMatcher 路徑匹配器

    基于Spring概念模型:PathMatcher 路徑匹配器

    這篇文章主要介紹了Spring概念模型:PathMatcher 路徑匹配器,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java類和對象習(xí)題及詳細答案解析

    Java類和對象習(xí)題及詳細答案解析

    這篇文章主要介紹了Java類和對象的相關(guān)知識,包括局部變量初始化、靜態(tài)方法、靜態(tài)導(dǎo)入、構(gòu)造方法、代碼塊執(zhí)行順序、toString方法重寫、類變量和靜態(tài)成員變量的訪問等,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-02-02
  • springboot日志切面通用類實例詳解

    springboot日志切面通用類實例詳解

    這篇文章主要介紹了springboot日志切面通用類,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • MyBatis實現(xiàn)簡單的數(shù)據(jù)表分月存儲

    MyBatis實現(xiàn)簡單的數(shù)據(jù)表分月存儲

    本文主要介紹了MyBatis實現(xiàn)簡單的數(shù)據(jù)表分月存儲,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • SpringCloud整合分布式服務(wù)跟蹤zipkin的實現(xiàn)

    SpringCloud整合分布式服務(wù)跟蹤zipkin的實現(xiàn)

    這篇文章主要介紹了SpringCloud整合分布式服務(wù)跟蹤zipkin的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Filter在springboot中的使用方法詳解

    Filter在springboot中的使用方法詳解

    這篇文章主要介紹了Filter在springboot中的使用方法詳解,filter(過濾器)作用于在intreceptor(攔截器)之前,不像intreceptor一樣依賴于springmvc框架,只需要依賴于serverlet,需要的朋友可以參考下
    2023-08-08

最新評論