java后端比较同类的两个对象的字段差异的项目内的三种实现的比较

文章目录

  • 前言
  • 一、示例1-OriginalUtils (不推荐)
  • 二、示例2-ExtendBeanComparer(不推荐)
  • 三、示例3-NativeBeanComparer(推荐)
  • 四、调试示例
    • 1.代码调试方法
    • 2.调试日志信息(印证了示例3的推荐结论)


前言

项目内有个需求,对导入的数据行,通过流程将数据下发到具体的业务人员端,由业务人员进行核对,然后由移动端APP,将核对后的前后差异的数据挂载到流程中去。需要提交的信息格式为“[{“fieldDesc”:“姓名”,“newValue”:“李四”,“fieldName”:“cnName”,“oldValue”:“张三”}]”,将每个不同的字段信息对比信息,包装到数组中统一挂载到流程中。本例介绍了项目内对象对比的三种实现方式,并对比了其中的实现差异,流程的相关操作不在本例介绍范围内。


一、示例1-OriginalUtils (不推荐)

本示例为初始状态的实现,在不引用第三方依赖的情况,基本实现了对象变更内容的比对,相比引用第三方工具包性能较好。在测试的过程中,暴露了一个日期数据未进行格式化的问题,可以针对日期类型,单独处理一下。本例中并未处理该问题,在项目中该示例已经被下面的第三方式直接替换了。

  • 使用java本身的API实现字段的读取和值的比对
  • 未对日期类型进行格式化处理

基于以上内容,第三方依赖的角度出发,在处理了日期类型格式化问题后,可以使用此示例中的实现。但是如果考虑更好的执行性能,不推荐该实现方式。代码如下(示例):

package com.nbcio.modules.flowable.utils;import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModelProperty;import java.lang.reflect.Field;
import java.util.*;public class OriginalUtils {/*** 获取对象的更新字段集合* @param oldObj 旧对象* @param newObj 新对象* @param excludeTableFieldExistFalse 是否要去除带有注解 @TableField(exist = false) 的属性。* @return* @param <T>*/public static <T> List<Map<String, Object>> compareChangeFields(T oldObj, T newObj,Boolean excludeTableFieldExistFalse)throws Exception {List<Map<String, Object>> result = new ArrayList<>();Field[] fields = oldObj.getClass().getDeclaredFields();for (Field field : fields) {// 设置可以访问私有字段field.setAccessible(true);if(checkExcludeFields(field,excludeTableFieldExistFalse)){continue;}// 判断字段值是否被更新if (field.get(newObj) != null && !field.get(newObj).equals(field.get(oldObj))) {System.out.println("字段:[ " + field.getName() + "]的值已更新,旧值【"+field.get(oldObj)+"】,新值【"+field.get(newObj)+"】");ApiModelProperty anno = field.getAnnotation(ApiModelProperty.class);Map<String, Object> map = new HashMap<>();map.put("fieldName",field.getName());map.put("fieldDesc",anno.value());map.put("oldValue",field.get(oldObj));map.put("newValue",field.get(newObj));result.add(map);}}return result;}/*** 要排除的属性*/private static List<String> excludeFields = Arrays.asList("id","createBy","createTime","updateBy","updateTime");/*** 检查需要排除的属性* @param field* @param excludeTableFieldExistFalse 是否要去除带有注解 @TableField(exist = false) 的属性。* @return* @param <T>*/private static <T> Boolean checkExcludeFields(Field field,Boolean excludeTableFieldExistFalse){if (field != null){String fieldName = field.getName();if (excludeFields.contains(fieldName)){return true;}if(excludeTableFieldExistFalse){TableField tableField = field.getAnnotation(TableField.class);if (tableField != null && !tableField.exist()){return true;}}}return false;}//    static void main(String[] args) {
//        WorkKeyPersonEntryCheck w1 = new WorkKeyPersonEntryCheck();
//        w1.setCnName("张三");
//        WorkKeyPersonEntryCheck w2 = new WorkKeyPersonEntryCheck();
//        w2.setCnName("李四");
//        w2.setId("234");
//        w2.setExts(new ArrayList<>());
//        w2.setPhone("18888");
//        System.out.println(compareChangeFields(w1,w2,false));
//    }
}

二、示例2-ExtendBeanComparer(不推荐)

本示例中使用了hutool工具包中的BeanUtil的api,将对象转换为Map键值对,然后通过一定规则,将键值对转换为Set集合;使用guava的Sets工具的api,求取两个对比对象转换后的Set集合的差集;基于差集,循环构建对比对象新旧的不同值并作为结果集返回。

  • 一下实现方式基于通用的工具类,利用集合的交、并、差等操作,可以方便的获取到不同的值。
  • 通用工具包多次对对象进行解析,对象转Map,获取对象的字段信息,字段构建Set集合,Set内容的再拆分。

基于以上问题,从执行性能、第三方依赖的角度出发,不建议使用此示例中的实现。代码如下(示例):

package com.nbcio.modules.flowable.jgpt.comparer;import cn.hutool.core.bean.BeanUtil;
import com.alibaba.druid.support.json.JSONUtils;
import com.google.common.collect.Sets;
import com.nbcio.modules.flowable.jgpt.entity.WorkKeyPersonEntryCheck;
import com.nbcio.modules.flowable.utils.JgUtils;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StopWatch;import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;import static java.util.stream.Collectors.toSet;/*** <h2>使用第三方工具实现的对象比较器</h2>** @Description* @Author misterbig* @Date 2024/2/2*/
@Slf4j
public class ExtendBeanComparer {/*** 对象字段和值之间的链接符号* {@value}*/public static final String FIELD_LINK_VALUE = "#";/*** 排除基础字段* {@value}*/private static final List<String> EXCLUDE_FIELDS = Arrays.asList("id", "createBy", "createTime"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/693558.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么使用Git进行版本恢复

场景 在实际工作过程中&#xff0c;有时候会出现以下问题&#xff1a; 1.在使用git对代码进行远程仓库托管时&#xff0c;会出现误操作&#xff0c;怎么恢复上一个版本或指定历史版本&#xff1f; 2.git 误操作&#xff0c;将代码提交到 master 主分支&#xff0c;怎么恢复 …

【洛谷 P8780】[蓝桥杯 2022 省 B] 刷题统计 题解(贪心算法+模拟+四则运算)

[蓝桥杯 2022 省 B] 刷题统计 题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 a a a 道题目&#xff0c;周六和周日每天做 b b b 道题目。请你帮小明计算&#xff0c;按照计划他将在第几天实现做题数大于等于 n n n 题? 输入格式 输入一…

tidb流式读取配置

程序中执行会话变量(显示数据速度)&#xff1a;--后是tidb默认值。 配合流式读取&#xff0c;作如下读取速度限制&#xff0c; 限制fullscan&index速度&#xff1a; 以下是在java中的示例&#xff0c;com.adata.common.tidb.read.是java包类名&#xff1a; com.adata.c…

模拟输入框

span 支持换行输入 <body>阿的<span contenteditable"true">大大</span>发送到发送到发多少分 </body>div <body><div contenteditable"true">大大</div> </body>

【AIGC】OpenAI推出王炸级模型sora,颠覆AI视频行业

文章目录 强烈推荐前言什么是OpenAI Sora&#xff1f;工作原理&#xff1a;算法原理&#xff1a;应用场景展望与其他视频生成模型相比有哪些优势和不足&#xff1f;优点缺点 总结强烈推荐专栏集锦写在最后 强烈推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易…

数据仓库概念梳理

数据仓库&#xff08;英语&#xff1a;Data Warehouse&#xff0c;简称数仓、DW&#xff09;,是一个用于存储、分析、报告的数据系统。数据仓库的目的是构建面向分析的集成化数据环境&#xff0c;为企业提供决策支持&#xff08;Decision Support&#xff09;。 数据仓库是分析…

初入职场的你,为何频繁跳槽?

大数据统计&#xff0c;初入职场的人跳槽频率相当高&#xff0c;而对于工作了2~3年的来说&#xff0c;跳槽频率也就没有那么频繁了&#xff0c;是什么原因导致了频繁跳槽&#xff1f;如何避免频繁跳槽呢&#xff1f; 是什么原因导致了跳槽&#xff1f; 不适应 从学校毕业&…

JS-异步编程-MDN文档学习笔记

异步JS 查看更多学习笔记&#xff1a;GitHub&#xff1a;LoveEmiliaForever MDN中文官网 异步编程简介 异步编程赋予程序如下特性 通过调用一个函数来启动一个长期运行的操作让函数开始操作并立即返回&#xff0c;这样我们的程序就可以保持对其他事件做出反应的能力当操作最…

【算法与数据结构】200、695、LeetCode岛屿数量(深搜+广搜) 岛屿的最大面积

文章目录 一、200、岛屿数量1.1 深度优先搜索DFS1.2 广度优先搜索BFS 二、695、岛屿的最大面积2.1 深度优先搜索DFS2.2 广度优先搜索BFS 三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、200、岛屿数量 1.1 深度优先搜…

2.Swift Tabbar的使用

Swift Tabbar的使用 在 Swift 中使用 UITabBarController 来创建一个具有选项卡界面的应用程序。下面是一个简单的示例&#xff0c;演示如何在 Swift 中使用 UITabBarController&#xff1a; import UIKitclass RootTabbar: UITabBarController {override func viewDidLoad()…

Redis篇----第十一篇

系列文章目录 文章目录 系列文章目录前言一、Redis 如何做内存优化?二、Redis 回收进程如何工作的?三、都有哪些办法可以降低 Redis 的内存使用情况呢?四、Redis 的内存用完了会发生什么?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下…

【前端素材】推荐优质后台管理系统Symox模板(适用电商,附带源码)

一、需求分析 后台管理系统是一种用于管理网站、应用程序或系统的工具&#xff0c;它通常作为一个独立的后台界面存在&#xff0c;供管理员或特定用户使用。下面详细分析后台管理系统的定义和功能&#xff1a; 1. 定义 后台管理系统是一个用于管理和控制网站、应用程序或系统…

LeetCode209长度最小子数组

参考链接&#xff1a;209.长度最小的子数组 注意&#xff1a;本题的子数组是连续的&#xff0c;一串一串的 class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {int i,j,minDis99999999;int sum0;//j控制子数组末尾&#xff0c;i控制子数…

gentoo安装笔记

最近比较闲&#xff0c;所以挑战一下自己&#xff0c;在自己的台式电脑上安装gentoo 下面记录了我亲自安装的步骤&#xff0c;作为以后我再次安装时参考所用。 整体步骤 一般来将一个linux发行版的安装步骤其实大体上都差不多&#xff0c;基本分为一下几步&#xff1a; 1. …

【算法与数据结构】1020、LeetCode飞地的数量

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;   程序如下&#xff1a; 复杂度分析&#xff1a; 时间复杂度&#xff1a; O ( ) O() O()。空间复杂…

RisingWave分布式SQL流处理数据库调研

概述 RisingWave是一款分布式SQL流处理数据库&#xff0c;旨在帮助用户降低实时应用的的开发成本。作为专为云上分布式流处理而设计的系统&#xff0c;RisingWave为用户提供了与PostgreSQL类似的使用体验&#xff0c;官方宣称具备比Flink高出10倍的性能&#xff08;指throughp…

快速清理_卸载docker_找到不用的进程_centos磁盘爆满_清理磁盘---Linux工作笔记071

查看大文件,并且按照大小排名 cd / | du -h |sort -hr|head -30 可以看到根据不用的结果进行删除 可以看到在/data/dict目录很大,里面的都可以删除 然后再去卸载docker,要不然,没有磁盘是卸载不了的 systemctl stop docker systemctl stop docker.socket yum remove docker-…

【2024上半年数学建模推荐】2024年第九届数维杯大学生数学建模挑战赛报名通知

2024上半年数模人必打的数学建模竞赛&#xff1a;数维杯全国大学生数学建模挑战赛已经开始报名。 赛题难度&#xff1a;四颗星 含金量&#xff1a;国家级二类 参赛对象&#xff1a;在校专科、本科、研究生 推荐理由&#xff1a;获奖率高&#xff0c;赛题难度比国赛略微简单…

Qt _day1

1.思维导图 2.设计一个简单登录界面 #include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {this->setWindowTitle("原神启动"); // this->setStyleSheet("background-color:rgb(255,184,64)");this->setStyl…

XSS攻击原理与解决方法

参考&#xff1a; web安全之XSS攻击原理及防范_xss攻击原理与解决方法-CSDN博客 跨站脚本攻击&#xff08;XSS)分类介绍及解决办法_反射型跨站脚本解决方案-CSDN博客 一、概述 XSS攻击是Web攻击中最常见的攻击方法之一&#xff0c;它是通过对网页注入可执行代码且成功地被浏…