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;
    }
}
相关推荐
NE_STOP2 小时前
Vide Coding--AI编程工具的选择
java
码云数智-园园2 小时前
C++20 Modules 模块详解
java·开发语言·spring
程序员黑豆2 小时前
JDK 下载安装与配置详细教程
java·前端·ai编程
小宇宙Zz2 小时前
Maven依赖冲突
java·服务器·maven
swordbob2 小时前
NIO的channel中什么是 fd(File Descriptor,文件描述符)
java·开发语言·nio
咖啡八杯3 小时前
GoF设计模式——享元模式
java·spring·设计模式·享元模式
十五喵源码网3 小时前
基于springboot2+vue2的租房管理系统
java·毕业设计·springboot·论文笔记
摇滚侠3 小时前
IDEA 创建 Java 项目 手动整合 SSM 框架
java·ide·intellij-idea
源分享3 小时前
Java线程同步的多种实现方法(非常详细)
java·开发语言·jvm
Flittly3 小时前
【AgentScope Java新手村系列】(10)实战-多Agent天气助手
java·spring boot·spring