Java利用Stream來實現多字段排序功能


場景:
奧運會時期,每場賽事后,對國家的金、銀、銅牌進行排序,排序規則如下:
先以金牌排序,金牌數越多,排得越前,如果金牌數相同,則比銀牌數,如果銀牌數一樣多,則比銅牌數,如果銅牌數還一樣多,則按國家英文字母順序升序排序。
例如:
China 51 20 21
American 50 1 1
Japan 0 0 0
上面是三個國家的獎牌數,每一行依次是國家名、金牌數、銀牌數、銅牌數。

需求:
請將獎牌按上面規則進行排序。

Java的一個實現:可以使用Stream進行多字段排序。

代碼:


import junit.framework.TestCase;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class Medal {
    private String country; // 國家
    private int gi; // 金牌數量
    private int si; // 銀牌數量
    private int bi; // 銅牌數量

    public Medal() {
    }

    public Medal(String country, int gi, int si, int bi) {
        this.country = country;
        this.gi = gi;
        this.si = si;
        this.bi = bi;
    }

    public String getCountry() {
        return country;
    }

    public int getGi() {
        return gi;
    }

    public int getSi() {
        return si;
    }

    public int getBi() {
        return bi;
    }

    /**
     * 使用Stream進行多字段排序
     *
     * @param paramArray
     * @return
     */
    public static List<String> rankByStream(String[] paramArray) {
        return Arrays.stream(paramArray).map(e -> {
            String[] array = e.split(" ");
            return new Medal(array[0], Integer.valueOf(array[1]), Integer.valueOf(array[2]), Integer.valueOf(array[3]));
        }).sorted(Comparator.comparing(Medal::getGi, Comparator.reverseOrder())
                .thenComparing(Medal::getSi, Comparator.reverseOrder())
                .thenComparing(Medal::getBi, Comparator.reverseOrder())
                .thenComparing(Medal::getCountry)).map(Medal::getCountry).collect(Collectors.toList());
    }

    public static void main(String[] args) {
        String[] testParam1 = new String[]{"China 51 20 21", "American 50 1 1", "Japan 0 0 0"}; // 測試用例1 入參
        List<String> expected1 = Arrays.asList("China", "American", "Japan"); // 測試用例1 返回結果

        String[] testParam2 = new String[]{"China 51 20 21", "American 52 1 1", "Japan 0 0 0"};
        List<String> expected2 = Arrays.asList("American", "China", "Japan");

        String[] testParam3 = new String[]{"China 51 20 21", "American 51 20 22", "Japan 53 0 0"};
        List<String> expected3 = Arrays.asList("Japan", "American", "China");

        String[] testParam4 = new String[]{"China 51 20 21", "American 50 1 1", "Japan 0 0 0", "France 51 20 20"};
        List<String> expected4 = Arrays.asList("China", "France", "American", "Japan");

        TestCase.assertEquals(expected1, Medal.rankByStream(testParam1));
        TestCase.assertEquals(expected2, Medal.rankByStream(testParam2));
        TestCase.assertEquals(expected3, Medal.rankByStream(testParam3));
        TestCase.assertEquals(expected4, Medal.rankByStream(testParam4));
    }
}

運行main方法,相關的測試案例均通過,返回結果與預期一致。

里面的核心方法是:stream.sorted(...).thenComparing(...),在我們這個例子中,需要進行四組排序,然后得到最后結果。

Stream不是一個集合,是一個流式的計算實現。
使用Stream.sorted(...).thenComparing(...),可以實現多字段的排序。
Stream是惰性求值,因此sorted、thenComparing等是在進行使用集合類進行存儲時,才會真正進行計算然后放入對應的容器。

那么stream的排序機制又是什么樣的呢?與我們經典冒泡等八大排序法有什么區別,Stream到底是有沒有自創出新的排序算法,還是說只是使用八大排序法之一進行了封裝?

下一篇將對Stream在多字段排序時的時間復雜度進行分析。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM