前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >java8 小技巧保证分组groupingBy后排序不变

java8 小技巧保证分组groupingBy后排序不变

作者头像
全栈程序员站长
发布2022-09-25 11:36:33
发布2022-09-25 11:36:33
1.6K00
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是你们的朋友全栈君。

问题:

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

排查

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

代码语言:javascript
代码运行次数:0
复制
//一个参数
   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数据集合,然后按照年龄排序,排序后进行分组,保证分组后顺序不变。

代码语言:javascript
代码运行次数:0
复制
//创建数据
 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

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/171442.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题:
  • 排查
  • 解决
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档