Java代码片段工具篇之StreamBinder数据分组简化

举报
西魏陶渊明 发表于 2022/09/25 05:26:13 2022/09/25
【摘要】 什么是分组,在写业务代码时候,经常会遇到分组的需求,将数据根据某一个条件分组成一对多,或者拆分成一对一的关系。JDK是对Stream提供了分组的方法但是不是特别好用,代码写起来也不够精简,为了让业务代码更...

什么是分组,在写业务代码时候,经常会遇到分组的需求,将数据根据某一个条件分组成一对多,或者拆分成一对一的关系。JDK是对Stream提供了分组的方法但是不是特别好用,代码写起来也不够精简,为了让业务代码更加精简,实现业务更简单。对数据分组抽象出一种分组能力。就是StreamBinder。

一、 为什么要精简它

因为记不住这个API,分组就是分组,但是方法是collect()。确实记不住,于是乎就对原始方法进行一个分组。但是遇到一个问题,是自己实现分组,还是使用上面那种分组呢? 通过Stream方法进行分组,在处理大批量数据时候效率会稍微高一点,但是处理几万时间并没有自己实现的效率高。

二、一对多分组

    /**
     * one to many
     * 分组根据相同条件分组
     *
     * @param dataSourceStream 数据流
     * @param <K>              key
     * @param <T>              value
     * @return Map
     */
    public static <K, T> Map<K, List<T>> group(Stream<T> dataSourceStream,
                                               Function<? super T, ? extends K> keyApply) {
        List<T> dataSources = dataSourceStream.collect(Collectors.toList());
        Map<K, List<T>> result = new HashMap<>(dataSources.size());
        for (T dataSource : dataSources) {
            K key = keyApply.apply(dataSource);
            List<T> ts = result.get(key);
            if (ts == null || ts.isEmpty()) {
                ArrayList<T> values = new ArrayList<>();
                values.add(dataSource);
                result.put(key, values);
            } else {
                ts.add(dataSource);
            }
        }
        return result;
    }

  
 

三、一对多分组并重新生成数据

可以看到下面代码是在上面代码的基础上,提供了一个valueApply映射。进行分组之后会在执行valueApply生成新的数据类型

 /**
     * one to many
     * 分组并对分组后的数据进行结构处理,注意出现相同的KEY值,会覆盖
     *
     * @param dataSourceStream 数据流
     * @param keyApply         key生成器
     * @param valueApply       value生成器
     * @param <K>              key
     * @param <V>              value
     * @param <T>              数据源
     * @return Map
     */
    public static <K, V, T> Map<K, List<V>> group(Stream<T> dataSourceStream, Function<? super T, ? extends K> keyApply,
                                                  Function<? super T, ? extends V> valueApply) {
        Map<K, List<T>> beforeGroup = group(dataSourceStream, keyApply);
        Map<K, List<V>> afterGroup = new HashMap<>(beforeGroup.size());
        for (Map.Entry<K, List<T>> kListEntry : beforeGroup.entrySet()) {
            K groupKey = kListEntry.getKey();
            List<T> groupValues = kListEntry.getValue();
            List<V> collect = groupValues.stream().map(valueApply).collect(Collectors.toList());
            afterGroup.put(groupKey, collect);
        }
        return afterGroup;
    }

  
 

四、一对一分组

一对一可以叫分组,也可以叫拆分。在项目中我们经常会处理一对一的映射关系。比如根据名字就找到指定的人。既然是一对一映射关系,如果出现了一对多关系就报一个异常 DuplicateFormatFlagsException。

    /**
     * one to one
     * 拆解,将数据拆解成一一对应的关系
     *
     * @param dataSourceStream 数据流
     * @param keyApply         key生成器
     * @param <K>              key
     * @param <T>              数据源
     * @return Map
     */
    public static <K, T> Map<K, T> dismantling(Stream<T> dataSourceStream,
                                               Function<? super T, ? extends K> keyApply) {
        return dismantling(dataSourceStream, keyApply, Function.identity());
    }

    /**
     * one to one
     * 拆解,将数据拆解成一一对应的关系
     *
     * @param dataSourceStream 数据流
     * @param keyApply         key生成器
     * @param valueApply       value生成器
     * @param <K>              key
     * @param <V>              value
     * @param <T>              数据源
     * @return Map
     */
    public static <K, V, T> Map<K, V> dismantling(Stream<T> dataSourceStream, Function<? super T, ? extends K> keyApply,
                                                  Function<? super T, ? extends V> valueApply) {
        Map<? extends K, List<T>> group = group(dataSourceStream, keyApply);
        Map<K, V> result = new HashMap<>(group.size());
        for (Map.Entry<? extends K, List<T>> entry : group.entrySet()) {
            K key = entry.getKey();
            List<T> oldValues = entry.getValue();
            if (oldValues == null || oldValues.isEmpty()) {
                continue;
            }
            if (oldValues.size() > 1) {
                throw new DuplicateFormatFlagsException(String.format("数据重复,请检查绑定key=%s,value=[%s]", key, oldValues));
            }
            V newValue = valueApply.apply(oldValues.get(0));
            result.put(key, newValue);
        }
        return result;
    }

  
 

可能用户想自定义异常,同样提供构造实现

 /**
     * one to one
     * 拆解,将数据拆解成一一对应的关系
     *
     * @param dataSourceStream  数据流
     * @param keyApply          key生成器
     * @param valueApply        value生成器
     * @param exceptionSupplier 异常生成
     * @param <K>               key
     * @param <V>               value
     * @param <T>               数据源
     * @param <X>               异常泛型
     * @return Map
     * @throws X Throwable
     */
    public static <K, V, T, X extends Throwable> Map<K, V> dismantling(Stream<T> dataSourceStream,
                                                                       Function<? super T, ? extends K> keyApply,
                                                                       Function<? super T, ? extends V> valueApply,
                                                                       Supplier<? extends X> exceptionSupplier) throws X {
        Map<? extends K, List<T>> group = group(dataSourceStream, keyApply);
        Map<K, V> result = new HashMap<>(group.size());
        for (Map.Entry<? extends K, List<T>> entry : group.entrySet()) {
            K key = entry.getKey();
            List<T> oldValues = entry.getValue();
            if (oldValues == null || oldValues.isEmpty()) {
                continue;
            }
            if (oldValues.size() > 1) {
                throw exceptionSupplier.get();
            }
            V newValue = valueApply.apply(oldValues.get(0));
            result.put(key, newValue);
        }
        return result;
    }

  
 

五、快速使用

        <dependency>
            <groupId>com.hanframework</groupId>
            <artifactId>common-toolkit</artifactId>
            <version>1.0.0-RELEASE</version>
        </dependency>

  
 

文章来源: springlearn.blog.csdn.net,作者:西魏陶渊明,版权归原作者所有,如需转载,请联系作者。

原文链接:springlearn.blog.csdn.net/article/details/105872507

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。