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;
    }
}
相关推荐
南宫生1 小时前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode
计算机毕设定制辅导-无忧学长2 小时前
Maven 基础环境搭建与配置(一)
java·maven
风与沙的较量丶3 小时前
Java中的局部变量和成员变量在内存中的位置
java·开发语言
m0_748251723 小时前
SpringBoot3 升级介绍
java
极客先躯4 小时前
说说高级java每日一道面试题-2025年2月13日-数据库篇-请说说 MySQL 数据库的锁 ?
java·数据库·mysql·数据库的锁·模式分·粒度分·属性分
程序员侠客行4 小时前
Spring事务原理 二
java·后端·spring
小猫猫猫◍˃ᵕ˂◍4 小时前
备忘录模式:快速恢复原始数据
android·java·备忘录模式
liuyuzhongcc4 小时前
List 接口中的 sort 和 forEach 方法
java·数据结构·python·list
五月茶4 小时前
Spring MVC
java·spring·mvc
sjsjsbbsbsn5 小时前
Spring Boot定时任务原理
java·spring boot·后端