Java比较两个对象是否相同并获取值不同的属性

男娘i 2023-09-26 10:32 120阅读 0赞

最近项目中要加操作日志,同时要把用户修改了那些字段记录下来,在更新的时候就需要比较之前的数据和现在的数据有哪些不同,这么多类一个一个的比较就太麻烦了,所以打算写一个工具类。

主要思想还是通过反射获取类的属性的getter方法,调用getter方法获取值并比较是否相同,相同就忽略不同就返回属性信息,方法都不复杂,主要是利用反射思想。

代码如下: 定义一个类保存比较后的返回值信息

  1. @Data
  2. public class PropertyModelInfo {
  3. //属性名
  4. private String propertyName;
  5. // 属性值
  6. private Object value;
  7. // 返回值类型
  8. private Class<?> returnType;
  9. }
  10. 复制代码

修改后的属性信息:

  1. public class ModifiedPropertyInfo implements Serializable {
  2. // 对应的属性名
  3. private String propertyName;
  4. // 未修改之前的值
  5. private Object oldValue;
  6. // 修改后的值
  7. private Object newValue;
  8. }
  9. 复制代码

逻辑代码:

  1. /**
  2. * 比较两个对象属性值是否相同
  3. * 如果不同返回修改过的属性信息
  4. * @param oldObj
  5. * @param newObj
  6. * @param ignoreProperties
  7. * @param <T>
  8. * @return 修改过的属性字段
  9. */
  10. public static <T> List<ModifiedPropertyInfo> getDifferentProperty(T oldObj , T newObj , String... ignoreProperties){
  11. if (oldObj != null && newObj != null) {
  12. // 比较全部字段
  13. if (ignoreProperties == null || ignoreProperties.length > 0) {
  14. if (oldObj.equals(newObj)) {
  15. return Collections.emptyList();
  16. }
  17. }
  18. List<PropertyModelInfo> oldObjectPropertyValue = getObjectPropertyValue(oldObj, ignoreProperties);
  19. if (!CollectionUtils.isEmpty(oldObjectPropertyValue)) {
  20. List<ModifiedPropertyInfo> modifiedPropertyInfos = new ArrayList<>(oldObjectPropertyValue.size());
  21. List<PropertyModelInfo> newObjectPropertyValue = getObjectPropertyValue(newObj, ignoreProperties);
  22. Map<String , Object> objectMap = new HashMap<>(newObjectPropertyValue.size());
  23. // 获取新对象所有属性值
  24. for (PropertyModelInfo propertyModelInfo : newObjectPropertyValue) {
  25. String propertyName = propertyModelInfo.getPropertyName();
  26. Object value = propertyModelInfo.getValue();
  27. objectMap.put(propertyName , value);
  28. }
  29. for (PropertyModelInfo propertyModelInfo : oldObjectPropertyValue) {
  30. String propertyName = propertyModelInfo.getPropertyName();
  31. Object value = propertyModelInfo.getValue();
  32. if (objectMap.containsKey(propertyName)) {
  33. Object newValue = objectMap.get(propertyName);
  34. ModifiedPropertyInfo modifiedPropertyInfo = new ModifiedPropertyInfo();
  35. if (value != null && newValue != null) {
  36. // 是否相等
  37. boolean equal = false;
  38. if (value instanceof BigDecimal) {
  39. // BigDecimal 用 equal 比较
  40. if (((BigDecimal) value).compareTo((BigDecimal) newValue) != 0) {
  41. equal = true;
  42. }
  43. }else if (!value.equals(newValue)) {
  44. equal = true;
  45. }
  46. if (equal) {
  47. modifiedPropertyInfo.setProperty(propertyName);
  48. modifiedPropertyInfo.setOldValue(value);
  49. modifiedPropertyInfo.setNewValue(newValue);
  50. modifiedPropertyInfos.add(modifiedPropertyInfo);
  51. }
  52. }else if (value != null || newValue != null){
  53. modifiedPropertyInfo.setProperty(propertyName);
  54. modifiedPropertyInfo.setOldValue(value);
  55. modifiedPropertyInfo.setNewValue(newValue);
  56. modifiedPropertyInfos.add(modifiedPropertyInfo);
  57. }
  58. }
  59. }
  60. return modifiedPropertyInfos;
  61. }
  62. }
  63. return Collections.emptyList();
  64. }
  65. /**
  66. * 通过反射获取对象的属性名称、getter返回值类型、属性值等信息
  67. * @param obj
  68. * @param ignoreProperties
  69. * @param <T>
  70. * @return
  71. */
  72. public static <T> List<PropertyModelInfo> getObjectPropertyValue(T obj , String... ignoreProperties){
  73. if (obj != null) {
  74. Class<?> objClass = obj.getClass();
  75. PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(objClass);
  76. List<PropertyModelInfo> modelInfos = new ArrayList<>(propertyDescriptors.length);
  77. List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
  78. for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
  79. Method readMethod = propertyDescriptor.getReadMethod();
  80. String name = propertyDescriptor.getName();
  81. if (readMethod != null && (ignoreList == null || !ignoreList.contains(name))) {
  82. Object invoke = null;
  83. Class<?> returnType = readMethod.getReturnType();
  84. try {
  85. invoke = readMethod.invoke(obj);
  86. PropertyModelInfo propertyModelInfo = new PropertyModelInfo();
  87. propertyModelInfo.setPropertyName(name);
  88. propertyModelInfo.setValue(invoke);
  89. propertyModelInfo.setReturnType(returnType);
  90. modelInfos.add(propertyModelInfo);
  91. } catch (IllegalAccessException | InvocationTargetException e) {
  92. LOGGER.error("反射获取类【"+objClass.getName()+"】方法异常," , e);
  93. }
  94. }
  95. }
  96. return modelInfos;
  97. }
  98. return Collections.emptyList();
  99. }
  100. 复制代码

测试:

  1. HouseInfo houseInfo = new HouseInfo();
  2. houseInfo.setAddress("test1");
  3. HouseInfo houseInfo2 = new HouseInfo();
  4. houseInfo2.setAddress("test2");
  5. //改变值
  6. List<ModifiedPropertyInfo> modifiedPropertyInfos = ReflectUtil.getDifferentProperty(houseInfo, houseInfo2);
  7. System.out.println(modifiedPropertyInfos);
  8. // 不改变值
  9. houseInfo2.setAddress("test1");
  10. modifiedPropertyInfos = ReflectUtil.getDifferentProperty(houseInfo, houseInfo2);
  11. System.out.println(modifiedPropertyInfos);
  12. 复制代码

结果:

  1. [ModifiedPropertyInfo(propertyName=address, oldValue=test1, newValue=test2)]
  2. []
  3. 复制代码

实现步骤:

1、获取对象的属性属性值
2、跟另一个对象的所有属性值比较

能力一般,水平有限,如有错误,请多指出

发表评论

表情:
评论列表 (有 0 条评论,120人围观)

还没有评论,来说两句吧...

相关阅读