zoukankan      html  css  js  c++  java
  • java8 小技巧保证分组groupingBy后排序不变

    问题:
    遇到一个小问题,查询出来一组数据后,按照其中的属性进行groupBy 分组 ,分组后要保证顺序不变。但是实际用groupBy进行分组后,返回的数据是杂乱无章的,没有按照原来list 的顺序返回

    排查
    首先去api中查找解决,查看Java 的 java.util.stream 包 Collectors 类 groupingBy 方法实现,结果如下:

    //一个参数
       public static <T, K> Collector<T, ?, Map<K, List<T>>>
        groupingBy(Function<? super T, ? extends K> classifier) {
            return groupingBy(classifier, toList());
        }

    //两个参数
        public static <T, K, A, D>
        Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
                                              Collector<? super T, A, D> downstream) {
            return groupingBy(classifier, HashMap::new, downstream);
        }
        
    //三个参数
      public static <T, K, D, A, M extends Map<K, D>>
        Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
                                      Supplier<M> mapFactory,
                                      Collector<? super T, A, D> downstream) {......}

    通过java api 发现 groupingBy 调用是内部自己创建了一个 HashMap ( HashMap::new)。因为 hashMap,是无无序的,是根据key的hashcode进行hash,然后放入对应的地方。所以在按照一定顺序put进HashMap中,然后遍历出HashMap的顺序跟put的顺序不同。

    知道这个了就明白了为什么无序了。所以我们直接调用三个参数的 groupingBy 方法mapFactory ,传入有顺序的Map, LinkedHashMap 就可以了。

    关于 LinkedHashMap 的信息自行百度

    解决
    创建Person数据集合,然后按照年龄排序,排序后进行分组,保证分组后顺序不变。

    //创建数据
     private static List<Person> getPersionList() {
            List<Person> persons = new ArrayList<>();
            for (int i = 1; i <= 40; i++) {
                Random r = new Random();
                Person person = new Person();
                person.setName("abel-" + i);
                person.setSex((int) (Math.random() * 2));
                person.setGroup(String.valueOf(i%2));
                person.setAge(25 + r.nextInt(50));
                persons.add(person);
            }
            return persons;

        }


        /**
         * 分组
         */
        private static void groupByTest() {
            List<Person> persons = getPersionList();
            //将list 排序,并按照排序后的结果进行有序分组
            LinkedHashMap<Integer, List<Person>> ageMap = personsSort.stream().sorted(Comparator.comparingInt(Person::getAge)).collect(Collectors.groupingBy(Person::getAge, LinkedHashMap::new, Collectors.toList()));
        }

    关于 排序Comparator.comparingInt 参考:
    https://www.jianshu.com/p/3f621e51f3

  • 相关阅读:
    洛谷P4304 [TJOI2013]攻击装置 题解
    洛谷P2172 [国家集训队]部落战争 题解
    CentOS 7.0下配置MariaDB数据库
    读《深入php面向对象、模式与实践》有感(三)
    读《深入php面向对象、模式与实践》有感(二)
    读《深入php面向对象、模式与实践》有感(一)
    Linux下配置Lamp
    自己编写php框架(一)
    php读取html文件(或php文件)的方法
    Thinkphp框架感悟(二)
  • 原文地址:https://www.cnblogs.com/zhuyeshen/p/12529592.html
Copyright © 2011-2022 走看看