Java对象列表属性映射工具类

背景

经常有这种情况,就是获取到一个对象列表之后,需要根据对象里某个字段的值去获取另一个字段的值。如下所示,有个Item对象列表,Item对象里有个id字段和Value字段,现需要根据id的值去查询value的值。

java 复制代码
        // 测试数据
        List<Item> items = Arrays.asList(
                new Item("1", "Item1"),
                new Item("2", "Item2"),
                new Item("3", "Item3")
        );
java 复制代码
    @Data
    static class Item {
        private final String id;
        private final String name;
        private String value;

        public Item(String id, String name) {
            this.id = id;
            this.name = name;
        }
    }

    @Data
    static class Value {
        private String id;
        private String value;

        public Value(String id, String value) {
            this.id = id;
            this.value = value;
        }
    }

实现

常规写法

如下:

java 复制代码
        // 先将id取出来
        List<String> ids = items.stream().map(Item::getId).collect(Collectors.toList());
        // 根据id获取value
        Map<String, Value> valueMap = getValueMap(ids);
        // 遍历items,设置value
        items.stream().forEach(item -> {
            String id = item.getId();
            Value value = valueMap.get(id);
            if (Objects.nonNull(value)) {
                item.setValue(value.getValue());
            }
        });

使用工具类

写法如下:

java 复制代码
        Collection<Item> res = keyValueMapping(
                items,
                Item::getId,
                keys -> getValueList(keys),
                Value::getId,
                (item, values) -> item.setValue(values.get(0).getValue()),
                false
        );

    // 模拟工具id获取value
    public static List<Value> getValueList(List<String> ids) {
        List<Value> values = Lists.newArrayList();
        for (String id : ids) {
            values.add(new Value(id, "Value" + id));
        }
        values.remove(2);
        return values;
    }

工具类代码

java 复制代码
public class FieldMappingUtil {
    private FieldMappingUtil() {
    }

    public static <T, K, V> void keyValueMapping(Collection<T> list, Function<T, K> getKey,
                                                 Function<List<K>, List<V>> key2Values,
                                                 Function<V, K> valueGroup,
                                                 BiConsumer<T, List<V>> setGroupedValues) {
        keyValueMapping(list, getKey, key2Values, valueGroup, setGroupedValues, false);
    }

    public static <T, K, V> void keyValueMapping(Collection<T> list, Function<T, K> getKey,
                                                 Function<List<K>, List<V>> key2Values,
                                                 Function<V, K> valueGroup,
                                                 BiConsumer<T, List<V>> setGroupedValues,
                                                 Consumer<Collection<T>> unmappedData) {
        boolean returnUnmappedData = Objects.nonNull(unmappedData);
        Collection<T> unmapped = keyValueMapping(list, getKey, key2Values,
                valueGroup, setGroupedValues, returnUnmappedData);
        if (returnUnmappedData && CollUtil.isNotEmpty(unmapped)) {
            unmappedData.accept(unmapped);
        }
    }

    public static <T, K, V, R> R keyValueMappingReturn(Collection<T> list,
                                                       Function<T, K> getKey,
                                                       Function<List<K>, List<V>> key2Values,
                                                       Function<V, K> valueGroup,
                                                       BiConsumer<T, List<V>> setGroupedValues,
                                                       Function<Collection<T>, R> unmappedData) {
        boolean returnUnmappedData = Objects.nonNull(unmappedData);
        Collection<T> unmapped = keyValueMapping(list, getKey, key2Values,
                valueGroup, setGroupedValues, returnUnmappedData);
        if (returnUnmappedData && CollUtil.isNotEmpty(unmapped)) {
            return unmappedData.apply(unmapped);
        }
        return null;
    }


    private static <T, K, V> Collection<T> keyValueMapping(Collection<T> list,
                                                           Function<T, K> getKey,
                                                           Function<List<K>, List<V>> key2Values,
                                                           Function<V, K> valueGroup,
                                                           BiConsumer<T, List<V>> setGroupedValues,
                                                           boolean returnUnmappedData) {
        if (CollUtil.isNotEmpty(list)) {
            // 源数据中非空的key
            List<K> nonNullKeys = list.stream().map(getKey).filter(Objects::nonNull).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(nonNullKeys)) {
                // 根据源数据获取目标数据
                List<V> allValues = key2Values.apply(nonNullKeys);
                if (CollUtil.isNotEmpty(allValues)) {
                    // 目标数据按照key分组
                    Map<K, List<V>> map = allValues.stream().collect(Collectors.groupingBy(valueGroup));
                    // 遍历源数据,设置分组后的目标值
                    return list.stream().filter(t -> {
                        // 获取当前对象key
                        K key = getKey.apply(t);
                        // 根据key获取目标数据
                        List<V> values = map.get(key);
                        if (CollUtil.isNotEmpty(values)) {
                            // 设置目标值到当前对象
                            setGroupedValues.accept(t, values);
                            return true;
                        } else {
                            return returnUnmappedData;
                        }
                    }).collect(Collectors.toList());
                }
            }
        }
        return returnUnmappedData ? list : null;
    }
}
相关推荐
达文汐4 分钟前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
培风图南以星河揽胜5 分钟前
Java版LeetCode热题100之零钱兑换:动态规划经典问题深度解析
java·leetcode·动态规划
启山智软28 分钟前
【中大企业选择源码部署商城系统】
java·spring·商城开发
我真的是大笨蛋31 分钟前
深度解析InnoDB如何保障Buffer与磁盘数据一致性
java·数据库·sql·mysql·性能优化
怪兽源码1 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
恒悦sunsite1 小时前
Redis之配置只读账号
java·redis·bootstrap
梦里小白龙1 小时前
java 通过Minio上传文件
java·开发语言
人道领域1 小时前
javaWeb从入门到进阶(SpringBoot事务管理及AOP)
java·数据库·mysql
sheji52612 小时前
JSP基于信息安全的读书网站79f9s--程序+源码+数据库+调试部署+开发环境
java·开发语言·数据库·算法
毕设源码-邱学长2 小时前
【开题答辩全过程】以 基于Java Web的电子商务网站的用户行为分析与个性化推荐系统为例,包含答辩的问题和答案
java·开发语言