• 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在多字段排序时的时间复杂度进行分析。

  • 相关阅读:
    Css颜色定义的方法汇总color属性设置方式
    关于css中的align-content属性详解
    关于char 指针变量char *=p;这个语句的输出问题
    事件绑定3
    事件绑定2
    事件绑定1
    XPath 初步讲解
    JSON初探
    CSS 媒体类型
    CSS Positioning(定位)
  • 原文地址:https://www.cnblogs.com/qujiayuan/p/12902380.html
Copyright © 2020-2023  润新知