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 分钟前
力扣Hot100系列20(Java)——[动态规划]总结(下)( 单词拆分,最大递增子序列,乘积最大子数组 ,分割等和子集,最长有效括号)
java·leetcode·动态规划
清水白石00811 分钟前
深入解析 LRU 缓存:从 `@lru_cache` 到手动实现的完整指南
java·python·spring·缓存
符哥200824 分钟前
C++ 进阶知识点整理
java·开发语言·jvm
Sayuanni%336 分钟前
初阶_多线程1(线程含义与关键属性)
java
程序媛徐师姐37 分钟前
Java基于微信小程序的模拟考试系统,附源码+文档说明
java·微信小程序·java模拟考试系统小程序·模拟考试微信小程序·模拟考试系统小程序·模拟考试小程序·java模拟考试小程序
疯狂敲代码的老刘1 小时前
JDK 1.6到25 全版本网盘合集 (Windows + Mac + Linux)
java·linux·windows·macos·jdk
夕除1 小时前
js--15
java·jvm·spring
曾经的三心草1 小时前
redis-9-集群
java·redis·mybatis
sun03221 小时前
【架构基础】Spring中的PropertySourcesPlaceholderConfigurer介绍 (并非新知识,比较古老的一种使用方式)
java·spring·架构
chilavert3181 小时前
技术演进中的开发沉思-356:重排序(中)
java·开发语言