概述
有时会遇到获取一个class下2个对象相同属性的不同值的属性。方便在页面上展示差异属性,标识个颜色啥的。
代码Demo
package xxx.xxx.xxx.xxx;
import com.xxx.xxx.xxx.ProductSkuBaseInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import java.beans.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Slf4j
public class Util {
public static void main(String[] args) {
ProductSkuBaseInfoVO source = new ProductSkuBaseInfoVO();
source.setCategoryId(111L);
source.setDepartmentId(222L);
ProductSkuBaseInfoVO target = new ProductSkuBaseInfoVO();
target.setCategoryId(112L);
target.setDepartmentId(322L);
List<String> list = compareDiffField(source, target);
System.out.println(list);
}
public static List<String> compareDiffField(Object source, Object target, String... ignoreFiledNames){
List<String> diffFieldNames = new ArrayList<>(20);
if(Objects.isNull(source) || Objects.isNull(target)){
return diffFieldNames;
}
Class<?> sourceClass = source.getClass();
Class<?> targetClass = target.getClass();
BeanInfo sourceBeanInfo = null;
BeanInfo targetBeanInfo = null;
try {
//一段时间内可以重复使用,内部get时候的 beanInfoCache 是一个WeakHashMap,每次gc被回收
sourceBeanInfo = Introspector.getBeanInfo(sourceClass);
targetBeanInfo = Introspector.getBeanInfo(targetClass);
} catch (IntrospectionException e) {
log.error("获取对象BeanInfo失败");
return diffFieldNames;
}
List<PropertyDescriptor> sourcePropertyDescriptors = Arrays.asList(sourceBeanInfo.getPropertyDescriptors());
Map<String, PropertyDescriptor> targetPropertyDescriptorMap = Stream
.of(targetBeanInfo.getPropertyDescriptors())
.collect(
Collectors.toMap(
FeatureDescriptor::getName,
it -> it,
(k1, k2) -> k2
)
);
if(ArrayUtils.isNotEmpty(ignoreFiledNames)){
//忽略指定的属性的比较
sourcePropertyDescriptors = sourcePropertyDescriptors
.stream()
.filter(it -> !ArrayUtils.contains(ignoreFiledNames, it.getName()))
.collect(Collectors.toList());
}
for (PropertyDescriptor sourcePropertyDescriptor : sourcePropertyDescriptors) {
String propertyName = sourcePropertyDescriptor.getName();
PropertyDescriptor targetPropertyDescriptor = targetPropertyDescriptorMap.get(propertyName);
if(Objects.isNull(targetPropertyDescriptor)){
//目标对象不存在此属性
continue;
}
Method sourceReadMethod = sourcePropertyDescriptor.getReadMethod();
Method targetReadMethod = targetPropertyDescriptor.getReadMethod();
if(Objects.isNull(sourceReadMethod) || Objects.isNull(targetReadMethod)){
//未找到get方法
continue;
}
try {
Object sourceReadValue = sourceReadMethod.invoke(source);
Object targetReadValue = targetReadMethod.invoke(target);
if(!Objects.equals(sourceReadValue, targetReadValue)){
//收集值有差异的属性name
diffFieldNames.add(propertyName);
}
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("比较获取不同属性方法出现异常,e:{0}", e);
}
}
return diffFieldNames;
}
}