当前位置: 首页 > news >正文

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

背景

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

        // 测试数据List<Item> items = Arrays.asList(new Item("1", "Item1"),new Item("2", "Item2"),new Item("3", "Item3"));
    @Datastatic 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;}}@Datastatic class Value {private String id;private String value;public Value(String id, String value) {this.id = id;this.value = value;}}

实现

常规写法

如下:

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

使用工具类

写法如下:

        Collection<Item> res = keyValueMapping(items,Item::getId,keys -> getValueList(keys),Value::getId,(item, values) -> item.setValue(values.get(0).getValue()),false);// 模拟工具id获取valuepublic 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;}

工具类代码

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)) {// 源数据中非空的keyList<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 -> {// 获取当前对象keyK 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;}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 标准库标头 <barrier>(C++20)学习
  • 系统性舍弃,系统性获得
  • STM3学习记录
  • RabbitMQ创建交换机和队列——配置类 注解
  • 【C++】Linux平台C++实现简单socket通信
  • Python精选200Tips:126-130
  • SciPy 插值
  • CI/CD持续集成和持续部署以及相关软件的使用
  • xLSTM模型学习笔记
  • 商务办公tips1:如何将网页转换为pdf
  • 视频监控平台是如何运作的?EasyCVR视频汇聚平台的高效策略与实践
  • Adobe After Effects 2022 安装包及全家桶下载:永久免费提供完整安装指南
  • [数据集][目标检测]男女性别检测数据集VOC+YOLO格式9769张2类别
  • GeoPandas在地理空间数据分析中的应用
  • 源代码审查范围为:
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • 【刷算法】从上往下打印二叉树
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • CODING 缺陷管理功能正式开始公测
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • express.js的介绍及使用
  • orm2 中文文档 3.1 模型属性
  • Promise初体验
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • 包装类对象
  • 闭包--闭包之tab栏切换(四)
  • 初识 webpack
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 关于for循环的简单归纳
  • 诡异!React stopPropagation失灵
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 如何优雅地使用 Sublime Text
  • 异常机制详解
  • 赢得Docker挑战最佳实践
  • 中文输入法与React文本输入框的问题与解决方案
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • #java学习笔记(面向对象)----(未完结)
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #QT(QCharts绘制曲线)
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • (1)(1.9) MSP (version 4.2)
  • (LeetCode) T14. Longest Common Prefix
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (windows2012共享文件夹和防火墙设置
  • (二)测试工具
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (过滤器)Filter和(监听器)listener
  • (三)mysql_MYSQL(三)
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (转)Oracle存储过程编写经验和优化措施
  • (转)shell调试方法
  • ******IT公司面试题汇总+优秀技术博客汇总
  • .JPG图片,各种压缩率下的文件尺寸