精华内容
下载资源
问答
  • Java对比两个对象的不同 JDK版本:1.8 (由于用到了lambda、stream) Maven <!-- 用到了hutool一些工具类方法 --> <dependency> <groupId>cn.hutool</groupId> <artifactId>...

    Java对比两个对象的不同


    JDK版本:1.8 (由于用到了lambda、stream)
    Maven

    <!-- 用到了hutool的一些工具类方法 -->
    <dependency>
    	<groupId>cn.hutool</groupId>
    	<artifactId>hutool-all</artifactId>
    	<version>4.5.11</version>
    </dependency>
    <!-- lombok简化对象封装 -->
    <dependency>
    	<groupId>org.projectlombok</groupId>
    	<artifactId>lombok</artifactId>
    	<version>1.18.8</version>
    </dependency>
    

    假设我们现在有个需求,信息变更审核功能,要求要记录信息变更 修改前修改后 的值。
    eg: 姓名:由 张三 变更为 李四

    核心注解

    import java.lang.annotation.*;
    
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface ColumnName {
    
        /**
         * 字段名称
         * @return
         */
        String value() default "";
    
        /**
         * 当前字段的类型,如果是集合指定集合中的类型 
         * 基本类型 可不指定
         * 用于复杂类型 eg: Object | List<Object>
         * @return
         */
        Class<?> classType() default void.class;
    
        /**
         * 是否是集合类型
         * 如果是集合类型必须指定其
         * 1. 集合中存放的对象类型 {@link ColumnName#classType()}
         * 2. 集合中的对象的唯一标识 {@link ColumnName#onlyMark()}
         * @return
         */
        boolean isList() default false;
    
    
        /**
         * 如果是集合类型还要知道该集合对象中什么字段可以确定唯一 可多个 逗号隔开 eg: id,name
         * @return
         */
        String onlyMark() default "";
    
        /**
         * 如果是日期类型 可自定义日期格式
         * 默认 yyyy-MM-dd HH:mm:ss
         * 常用格式,包括:
         *      HH:mm:ss
         *      yyyy-MM-dd
         *      yyyy-MM-dd HH:mm
         *      yyyy-MM-dd HH:mm:ss
         *      yyyy-MM-dd HH:mm:ss.SSS
         * @return
         */
        String dateFormat() default "yyyy-MM-dd HH:mm:ss";
    }
    

    有了以上注解后我们来看我们要对比的实体类
    假设我们现在有一个人的类
    里面包含 编号、姓名、年龄、生日,以及这个人养的一条狗,以及一个女朋友的List集合

    人类

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Person {
    
        @ColumnName("编号")
        private Integer id;
    
        @ColumnName("姓名")
        private String name;
    
        @ColumnName("年龄")
        private Integer age;
    
        @ColumnName(value = "生日", dateFormat = "yyyy-MM-dd")
        private Date birthDay;
    
        @ColumnName(value = "狗", classType = Dog.class)
        private Dog dog;
    
        @ColumnName(value = "女朋友", isList= true, classType = GirlFriend.class, onlyMark = "id,age")
        private List<GirlFriend> girlFriends;
        
    }
    

    狗类

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Dog {
    
        @ColumnName("狗名字")
        private String name;
    
    }
    

    女朋友类

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class GirlFriend {
    
        @ColumnName("编号")
        private Integer id;
    
        @ColumnName("姓名")
        private String name;
    
        @ColumnName("年龄")
        private Integer age;
    
    }
    

    创建一个存放不同的类,又来存放最终对比出来的不同的结果

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Different {
    
        // 字段
        private String field;
    
        // 对应的字段提示 eg: 姓名
        private String fieldName;
    
        // 变更前的值
        private String oldData;
    
        // 变更后的值
        private String newData;
    
        @Override
        public String toString() {
            return "数据库字段:'" + field + "', 字段:'" + fieldName + '\'' + ", 老值:'" + oldData + '\'' + ", 新值:'" + newData + '\'';
        }
        
    }
    

    现在我们有一个修改之前的人对象和修改之后的人对象
    要求:获取到两者的不同之处

    public static void main(String[] args) throws Exception {
        // 修改之前的对象
        Person person1 = new Person();
        person1.setId(1);
        person1.setName("张三");
        person1.setBirthDay(DateUtil.parse("2018-05-05"));
    
        person1.setAge(18);
    
        Dog dog = new Dog();
        dog.setName("张三的狗");
        person1.setDog(dog);
    
        person1.setGirlFriends(Arrays.asList(
                new GirlFriend(1, "小花", 19)
                , new GirlFriend(2, "小丽", 20)
                , new GirlFriend(3, "小青", 10)
        ));
        
    	// 修改之后的对象
        Person person2 = new Person();
        person2.setId(1);
        person2.setName("张三");
        person2.setBirthDay(DateUtil.parse("2018-05-05"));
        person2.setAge(18);
    
        Dog dog2 = new Dog();
        dog2.setName("张三的狗");
        person2.setDog(dog2);
    
        person2.setGirlFriends(Arrays.asList(
                new GirlFriend(1, "小花", 19)
                , new GirlFriend(2, "小丽", 20)
                , new GirlFriend(3, "小青", 10)
        ));
    
        // 获取两个对象的不同
        getDifferents(person1, person2, Person.class).forEach(System.out::println);
    }
    

    我们修改 person2 的name 修改为: 张三三 并执行 Main
    可以得到以下结果
    在这里插入图片描述
    继续修改 person2 的birthday 修改为 :2018-10-10 并执行 Main
    可以得到以下结果
    在这里插入图片描述
    如果日期的格式不符合预期结果 可以在@ColumnName#dateFormat() 指定其日期的格式
    继续修改dog2的name 为:张三的大黑狗
    可以得到以下结果
    在这里插入图片描述
    复杂的类型需要在实体类中指定类型 eg:@ColumnName#classType()
    在这里插入图片描述
    我们继续修改女朋友的集合中的数据
    将名字叫小花的女朋友名字修改为 花姑娘 结果
    在这里插入图片描述
    由于集合会出现 添加、修改、删除三种 不同的情况
    所有这里再添加一个接口

    public interface FieldNameHandler {
    
        /**
         * 增
         */
        String ADDED_PREFIX = "addedPrefix";
    
        /**
         * 删
         */
        String DELETE_PREFIX = "deletePrefix";
    
        /**
         * 改
         */
        String UPDATE_PREFIX = "updatePrefix";
    
        /**
         * 处理添加字段名
         * @return 添加数据时的字段名前缀
         */
        String addedPrefix();
    
        /**
         * 处理删除字段名
         * @return 删除数据时的字段名前缀
         */
        String deletePrefix();
    
        /**
         * 处理修改字段名
         * @return 修改数据时的字段名前缀
         */
        String updatePrefix();
    
    }
    

    让我们的GirlFriend 实现 FieldNameHandler
    实现后我们的GirlFriend变成

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class GirlFriend implements FieldNameHandler {
    
        @ColumnName("编号")
        private Integer id;
    
        @ColumnName("姓名")
        private String name;
    
        @ColumnName("年龄")
        private Integer age;
    
        @Override
        public String addedPrefix() {
            return StrUtil.format("添加女朋友 ");
        }
    
        @Override
        public String deletePrefix() {
            return StrUtil.format("删除女朋友 ");
        }
    
        /**
         * 复杂类型的 变更字段 可以自定义
         * @return 返回值会加上 {@link ColumnName#value()} 的值
         * 如果当前对象的姓名改了 字段的值就为 : 修改编号为:1的女朋友
         */
        @Override
        public String updatePrefix() {
            return StrUtil.format("修改编号为:" + this.id + "的女朋友 ");
        }
    }
    

    我们再次运行Main
    在这里插入图片描述
    字段本来的值是@ColumnName#value() 的值 姓名 实现了FieldNameHandler接口后如果发现是新增、删除、修改
    会自动调用 实现类中的addedPrefix、deletePrefix、updatePrefix 并 加上@ColumnName#value()

    添加删除女朋友这里就不模拟了
    最后贴上getDifferents 写的比较粗糙 见谅

    /**
    * 数据修改对比统计
     *
     * @param oldT      修改前
     * @param newT      修改后
     * @param className 类名
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> List<Different> getDifferents(T oldT, T newT, Class<?> className) throws IllegalAccessException, InstantiationException {
    
        // 存放处理结果
        List<Different> differents = new ArrayList<>();
    
        // 获取当前类的所有字段
        Field[] fields = className.getDeclaredFields();
    
        for (Field f : fields) {
            // 过滤 static、 final、private static final字段
            if (f.getModifiers() == Modifier.FINAL || f.getModifiers() == Modifier.STATIC || f.getModifiers() == (Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL)) {
                continue;
            }
    
            // 获取当前字段注解
            ColumnName annotationColumn = f.getAnnotation(ColumnName.class);
            if (annotationColumn == null) {
                continue;
            }
    
            // 反射获取当前老对象的字段值
            Object oldV = ReflectUtil.getFieldValue(oldT, f.getName());
            // 反射获取当前新对象的字段值
            Object newV = ReflectUtil.getFieldValue(newT, f.getName());
    
            // 当前字段的类型 用于复杂类型 eg: Object List Set
            final Class<?> dataType = annotationColumn.classType();
            final String typeName = annotationColumn.classType().getTypeName();
    
            // 如果他是集合类型
            if (annotationColumn.isList()) {
                // 二次校验是否是集合类型
                if (Objects.isNull(oldV)) oldV = new ArrayList<>();
                if (Objects.isNull(newV)) newV = new ArrayList<>();
                final boolean isCollection = Collection.class.isAssignableFrom(oldV.getClass());
                if (isCollection) {
                    final List oldList = (List) oldV;
                    final List newList = (List) newV;
                    // 两个集合都是空的继续处理剩余字段
                    if (CollectionUtil.isEmpty(oldList) && CollectionUtil.isEmpty(newList)) {
                        continue;
                    }
    
                    // 老的是空的 新的有值 说明是集合中新添加了值 并不存在修改操作
                    if (CollectionUtil.isEmpty(oldList) && CollectionUtil.isNotEmpty(newList)) {
                        for (Object n : newList) {
                            differents.addAll(getDifferents(n.getClass().newInstance(), n, dataType));
                        }
                        continue;
                    }
    
                    // 新的是空的 老的有值 说明是集合中的值全部删除了
                    if (CollectionUtil.isNotEmpty(oldList) && CollectionUtil.isEmpty(newList)) {
                        for (Object o : oldList) {
                            differents.addAll(getDifferents(o, o.getClass().newInstance(), dataType));
                        }
                        continue;
                    }
                    // 创建临时集合
                    List allList = new ArrayList();
                    allList.addAll(oldList);
                    allList.addAll(newList);
    
                    for (Object o : oldList) {
                        int matchCount = 0;
                        for (Object n : newList) {
                            final String key = annotationColumn.onlyMark();
                            // 如果存在多个唯一标识字段特殊处理
                            if (key.contains(",")) {
                                final String[] keys = key.split(",");
                                boolean isSuccess = true;
                                for (String s : keys) {
                                    final Object o1 = ReflectUtil.getFieldValue(o, s);
                                    final Object n1 = ReflectUtil.getFieldValue(n, s);
    
                                    // 有一个不匹配跳出循环
                                    if (!o1.equals(n1)) {
                                        isSuccess = false;
                                        break;
                                    }
                                }
                                if (isSuccess) {
                                    // 匹配到就--
                                    matchCount--;
                                    differents.addAll(getDifferents(o, n, dataType));
                                } else {
                                    // 没有匹配到就++
                                    matchCount++;
                                    // 如果不是一个对象 就去判断该新对象是否是之前已经判断过了的对象
                                    final long count = allList.stream().filter(e -> {
                                        for (String s : keys) {
                                            final Object o1 = ReflectUtil.getFieldValue(e, s);
                                            final Object n1 = ReflectUtil.getFieldValue(n, s);
    
                                            // 有一个不匹配跳出循环
                                            if (!o1.equals(n1)) {
                                                return false;
                                            }
                                        }
                                        return true;
                                    }).count();
                                    if (count < 2) {
                                        // 说明是新添加了一个
                                        differents.addAll(getDifferents(o.getClass().newInstance(), n, dataType));
                                        allList.add(n);
                                    }
                                }
    
                            } else {
                                final Object o1 = ReflectUtil.getFieldValue(o, key);
                                final Object n1 = ReflectUtil.getFieldValue(n, key);
                                if (o1.equals(n1)) {
                                    // 匹配到就--
                                    matchCount--;
                                    differents.addAll(getDifferents(o, n, dataType));
                                } else {
                                    // 没有匹配到就++
                                    matchCount++;
                                    // 如果不是一个对象 就去判断该新对象是否是之前已经判断过了的对象
                                    final long count = allList.stream().filter(e -> ReflectUtil.getFieldValue(e, key).equals(ReflectUtil.getFieldValue(n, key))).count();
                                    if (count < 2) {
                                        // 说明是新添加了一个
                                        differents.addAll(getDifferents(o.getClass().newInstance(), n, dataType));
                                        allList.add(n);
                                    }
    
                                }
                            }
    
                        }
                        // 没配到说明是老数据本来有新的数据删除了
                        if (matchCount == newList.size()) {
                            differents.addAll(getDifferents(o, o.getClass().newInstance(), dataType));
                        }
    
                    }
    
                }
            }
    
            // 不能是 void 和 基本类型
            if (!"void".equals(typeName) && !ClassUtil.isBasicType(dataType)) {
                final Class<?> aClass = annotationColumn.classType();
                differents.addAll(getDifferents(oldV, newV, aClass));
                continue;
            }
    
            // 检查新老对象的值是否一致 不一致记录
            if (!Objects.equals(newV, oldV)) {
    
                // 字段名字
                String fieldName = StrUtil.isNotEmpty(annotationColumn.value()) ? annotationColumn.value() : f.getName();
    
                // 获取当前类所实现的所有接口
                final Class<?>[] interfaces = className.getInterfaces();
    
                // 是否实现了FieldNameHandler接口,如果实现了FieldNameHandler接口 就追加调用 FieldNameHandler#handle()
                final long count = Stream.of(interfaces).filter(a -> a.equals(FieldNameHandler.class)).count();
                if (count > 0) {
                    Object invoke = null;
                    // 添加了数据
                    if (oldT.getClass().newInstance().equals(oldT)) {
                        invoke = ReflectUtil.invoke(oldT, FieldNameHandler.ADDED_PREFIX);
                    }
                    // 删除了数据
                    else if (newT.getClass().newInstance().equals(newT)) {
                        invoke = ReflectUtil.invoke(oldT, FieldNameHandler.DELETE_PREFIX);
                    }
                    // 修改了数据
                    else {
                        invoke = ReflectUtil.invoke(oldT, FieldNameHandler.UPDATE_PREFIX);
                    }
                    if (Objects.nonNull(invoke)) {
                        fieldName = invoke + fieldName;
                    }
    
                }
    
                // 老对象值
                String oldValue = null != oldV ? oldV.toString() : "";
                // 新对象值
                String newValue = null != newV ? newV.toString() : "";
    
                // 日期格式特殊处理
                if (oldV instanceof Date && newV instanceof Date) {
                    if (StrUtil.isNotEmpty(oldValue)) {
                        oldValue = DateUtil.format((Date) oldV, annotationColumn.dateFormat());
                    }
                    if (StrUtil.isNotEmpty(newValue)) {
                        newValue = DateUtil.format((Date) newV, annotationColumn.dateFormat());
                    }
                }
    
                // 添加处理结果中
                differents.add(new Different(f.getName(), fieldName, oldValue, newValue));
            }
        }
        return differents;
    }
    

    转载注明出处 谢谢。

    展开全文
  • * 本实例意在对比以下两种方法创建对象实例: * 直接new对象 * 反射 * 直接new对象:无法访问SCP类中私有方法,仅能访问公有方法 * 反射:可访问private,default,protected,public任意方法 * 为...
    /**
     * 本实例意在对比以下两种方法创建对象实例:
     * 		直接new对象
     * 		反射
     *		直接new对象:无法访问SCP类中的私有方法,仅能访问公有方法
     *		反射:可访问private,default,protected,public任意方法	
     *	为清楚显示,用反射访问静态和非静态分成两个页面
     */
     
    //创建一个SCP类
    public class SCP {
        private String name;
        public int id;
        private String level;
        private static String gender;//静态属性
    
        public SCP() {
        }
    
        public SCP(String name, int id, String level) {
            this.name = name;
            this.id = id;
            this.level = level;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getLevel() {
            return level;
        }
    
        public void setLevel(String level) {
            this.level = level;
        }
    
        public static String getGender() {
            return gender;
        }
    
        public static void setGender(String gender) {
            SCP.gender = gender;
        }
    
        @Override
        public String toString() {
            return "SCP{" +
                    "name='" + name + '\'' +
                    ", id=" + id +
                    ", level='" + level + '\'' +
                    '}';
        }
        //自定义方法
        private String description (String des){
            System.out.println("表现出极高的" + des);
            return des;
        }
        //自定义静态方法
        private static void show(){
            System.out.println("SCP-682处决实验");
        }
    }
    
    /**
     * @author Prannt
     * 正常访问 SCP 类是这样的步骤,先 new对象(静态属性直接调用),再得到对象。
     * (包括静态属性和非静态属性,由于自定义方法show()已用private修饰,new对象访问不到)
     */
    public class TestCommon {
        public static void main(String[] args) {
            SCP scp1 = new SCP();
            scp1.setId(682);
            scp1.setName("不灭孽蜥");
            scp1.setLevel("Keter");
            SCP.setGender("未知");
            System.out.println("项目编号:" + "SCP-" + scp1.getId() + "," + scp1.getName()+ "。项目等级:" +
                    scp1.getLevel() + "。性别:" + SCP.getGender());
        }
    }
    

    打印结果如下图所示
    在这里插入图片描述

    //采用反射的方法(详细步骤),访问非静态属性和非静态方法
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class SCPTest {
        @Test
        //第一步:获取Class的三种方式,且三种方式等价
        public void step1() throws ClassNotFoundException {
            //方式一:
            Class<SCP> clazz1 = SCP.class; //加上泛型就不用强转了
            //方式二:
            SCP scp = new SCP();
            Class clazz2 = scp.getClass();
            //方式三:
            Class clazz3 = Class.forName("Summary.SCP");
            System.out.println(clazz3);
        }
        @Test
        //第二步:创建运行时类的对象
        public void step2() throws Exception {
            Class<SCP> clazz1 = SCP.class;
            SCP scp = clazz1.newInstance();
        }
        @Test
        //第三步:获取运行时类中指变量名的属性、方法
        public void step3() throws Exception {
            Class<SCP> clazz1 = SCP.class;
            SCP scp = clazz1.newInstance();
            //获取运行时类中指变量名的属性
            Field name = clazz1.getDeclaredField("name");
            Field id = clazz1.getDeclaredField("id");
            Field level = clazz1.getDeclaredField("level");
    
            //保证当前属性是可访问的
            name.setAccessible(true);
            id.setAccessible(true);
            level.setAccessible(true);
    
            //填参数
            name.set(scp,"不灭孽蜥");
            id.set(scp,682);
            level.set(scp,"Keter");
    
            System.out.println("项目编号:" + "SCP-" + id.get(scp) + "," + name.get(scp) + "。项目等级:" +
                    level.get(scp));
            System.out.println("");
    
            //获取运行时类中指变量名的方法
            Method description = clazz1.getDeclaredMethod("description", String.class);
            //保证当前属性是可访问的
            description.setAccessible(true);
            Object wisdom = description.invoke(scp, "智慧(这是private修饰的私有方法,访问到了)");//填参数
    
        }
    }
    

    采用反射打印结果如下
    在这里插入图片描述

    //采用反射的方法(详细步骤),访问静态属性和静态方法
    import Reflection2.Person1;
    import org.junit.Test;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    //下列代码为获取静态属性和静态方法
    public class SCPTestStatic {
        @Test
        public void testStatic() throws Exception {
            Class<SCP> clazz1 = SCP.class;
            SCP scp = clazz1.newInstance();
            //获取运行时类中指变量名的静态属性
            Field gender = clazz1.getDeclaredField("gender");//静态属性
            gender.setAccessible(true);
            gender.set(Person1.class,"未知");
            System.out.println("SCP-682的性别:" + gender.get(SCP.class));
    
            //获取运行时类中指变量名的静态方法
            Method show = clazz1.getDeclaredMethod("show");
            show.setAccessible(true);
            show.invoke(SCP.class);
        }
    }
    
    

    反射访问静态属性和静态方法如下图所示
    在这里插入图片描述

    展开全文
  • 一、背景介绍 最近重构一个项目,需要对比出旧系统和新系统对外提供接口...乍一听,对比两个对象蛮简单,但是如果对象结构比较复杂,对比还是比较麻烦,比如List嵌套Map,Map嵌套List,而且不能够确定嵌套...

    一、背景介绍

            最近重构一个项目,需要对比出旧系统和新系统对外提供接口的返回值是否相同,算是保障新系统正确上线吧。测开部门有专门的接口对比接口,为了保险,自己也写了一个对比两个对象是否相同,关于其他细节本文忽略,本文主要说对比两个对象是否相同。把差异输出出来,乍一听,对比两个对象蛮简单的,但是如果对象结构比较复杂,对比还是比较麻烦的,比如List嵌套Map,Map嵌套List,而且不能够确定嵌套的深度,代码该如何写。

    二、代码

             废话不多说直接上代码,可以自行测试,支持List,Map,以及普通对象之间的相互嵌套。采用递归,自己测了几次还管用着

    1、DiffExecute.class 就是实现对象对比的细节
    public class DiffExecute {
        
    
        /**
         * 对比接口结果
         * @param carsourceObj
         * @param popObj
         * @return
         */
        public boolean diffObject(String diffName, Object carsourceObj, Object popObj, List<NcDiffRecord> diffRecords) {
            if (carsourceObj == null && popObj == null) {
                return true;
            }
            if (isBaseType(carsourceObj, popObj)) {
                if (carsourceObj != null && !carsourceObj.equals(popObj)) {
                    addNcDiffRecord(carsourceObj, popObj, diffName, diffRecords);
                    return false;
                }else if (popObj != null && !popObj.equals(carsourceObj)) {
                    addNcDiffRecord(carsourceObj, popObj, diffName, diffRecords);
                    return false;
                } else {
                    return true;
                }
            }
            // 旧结果是list
            if (carsourceObj instanceof List) {
                // 新结果不是list报错
                if (!(popObj instanceof List)) {
                    addNcDiffRecord(carsourceObj, popObj, diffName+"的类型不同"+"<oldClass>=["+carsourceObj.getClass()+"]<newClass>=["+popObj.getClass()+"]", diffRecords);
                    return false;
                }
                Boolean result = true;
                List carsourList = (List) carsourceObj;
                List popList = (List) popObj;
                if (carsourList.size() != popList.size()) {
                    addNcDiffRecord(carsourceObj, popObj, diffName+"的集合长度不同", diffRecords);
                    return false;
                }
                for (int i = 0; i < carsourList.size(); i++) {
                    result = diffObject("list", carsourList.get(i), popList.get(i), diffRecords) && result;
                }
                return result;
            }
            // 旧的不是list,新结果如果是list那么就报错
            if (popObj instanceof List) {
                addNcDiffRecord(carsourceObj, popObj, diffName+"的类型不同"+"<oldClass>=["+carsourceObj.getClass()+"]<newClass>=["+popObj.getClass()+"]", diffRecords);
                return false;
            }
    
            Boolean result = true;
            Map<String, Object> carsourceMap = JSONObject.parseObject(JSONObject.toJSONString(carsourceObj));
            Map<String, Object> popMap = JSONObject.parseObject(JSONObject.toJSONString(popObj));
            if (carsourceMap.size() != popMap.size()) {
                addNcDiffRecord(carsourceObj, popObj, diffName+"对象属性数量不同", diffRecords);
                return false;
            }
            Set<String> keySet = carsourceMap.keySet();
            for (String carsourceKey : keySet) {
                // 属性缺失的情况
                if (!popMap.containsKey(carsourceKey)) {
                    addNcDiffRecord(carsourceMap.get(carsourceKey), null, "新结果没有属性为["+carsourceKey+"]的值", diffRecords);
                    continue;
                }
                result = diffObject(carsourceKey, carsourceMap.get(carsourceKey), popMap.get(carsourceKey), diffRecords) && result;
            }
            return result;
        }
    
        private boolean isBaseType(Object carsourceObj, Object popObj) {
            if (carsourceObj instanceof String) {
                return true;
            } else if (carsourceObj instanceof Integer) {
                return true;
            } else if (carsourceObj instanceof Character) {
                return true;
            } else if (carsourceObj instanceof Boolean) {
                return true;
            } else if (carsourceObj instanceof Long){
                return true;
            } else if (carsourceObj instanceof Byte) {
                return true;
            } else if (carsourceObj instanceof Double) {
                return true;
            } else if (carsourceObj instanceof Float) {
                return true;
            } else if (carsourceObj instanceof Short){
                return true;
            } else {
                return false;
            }
        }
    
        public void addNcDiffRecord(Object carsourceObj, Object popObj, String diffName, List<NcDiffRecord> diffRecords) {
            NcDiffRecord record = new NcDiffRecord();
            record.setExpectValue(JSONObject.toJSONString(carsourceObj));
            record.setActualValue(JSONObject.toJSONString(popObj));
            record.setNewDiffItemName(diffName);
            record.setOldDiffItemName(diffName);
            diffRecords.add(record);
        }
    
    }

    2、NcDiffRecord.class  主要记录差异的结果的

    public class NcDiffRecord implements Serializable {
        
        private Integer id;
        
        private Byte isDeleted;
    
        
        private Integer diffDependId;
    
        private String newDiffItemName;
    
        private String oldDiffItemName;
        private String expectValue;
        private String actualValue;
    
    }

    3、DiffExecuteTest.class  是测试类,为了大家好看,用来一个很简单的两个对象,大家可以自己造对象,进行对比。

    public class DiffExecuteTest {
        @Resource
        private DiffExecute diffExecute;
    
        
        @Test
        public void diffOneObject() {
            DiffExecute diffExecute = new DiffExecute();
            List<NcDiffRecord> result = Lists.newArrayList();
    
            GroupCityDTO cityDTO5 = new GroupCityDTO();
            cityDTO5.setCityCount(2);
            cityDTO5.setCityGroupAlias("你妹");
            cityDTO5.setCityIds(Lists.newArrayList(1,2,3));
            cityDTO5.setCityNames("猪你妹");
            cityDTO5.setCityGroupId(2312);
    
            GroupCityDTO cityDTO6 = new GroupCityDTO();
            cityDTO6.setCityCount(3);
            cityDTO6.setCityGroupAlias("呱你妹");
            cityDTO6.setCityIds(Lists.newArrayList(1,3));
            cityDTO6.setCityNames("猪你妹");
            cityDTO6.setCityGroupId(23132);
            diffExecute.diffObject("",cityDTO5, cityDTO6, result );
            System.out.println(result);
    
        }

    是不是很简单嘞!,嘿嘿,奥利给,对了,有啥问题,给我提建议。

    展开全文
  • 下面是对比代码 修改一下所要对比的对象和对比完返回的数据即可 /** * 获取差异项 */ private FinanceOrganizationCompare compareMainWithMinor(FinanceOrganizationNew main, FinanceOrganizationNew minor) ...

    首先创建一个映射差异项的实体类存放 对比字段和对比结果

    下面是对比代码 修改一下所要对比的对象和对比完返回的数据即可

    /**
     * 获取差异项
     */
    private FinanceOrganizationCompare compareMainWithMinor(FinanceOrganizationNew main, FinanceOrganizationNew minor) throws ServiceException {
        FinanceOrganizationCompare compareResult = new FinanceOrganizationCompare();
        //CompareWithApiResult compare = new CompareWithApiResult();
        PropertyDescriptor[] fields = BeanUtils.getPropertyDescriptors(main.getClass());
        int diffCount = 0;
        try {
            for (PropertyDescriptor field : fields) {
                Method readMethod = field.getReadMethod();
                Object mainObj = readMethod.invoke(main);
                Object minorObj = readMethod.invoke(minor);
                if (isIgnore(field)) {
                    continue;
                }
    
                boolean isSame = (mainObj == null && minor == null) || (mainObj != null && mainObj.equals(minorObj));
                CompareWithApiResult result = new CompareWithApiResult();
                if (!isSame && !field.getName().equals("organizationId")) {
                    diffCount++;
                    //result.setEqual(isSame);
                }
    
                if (field.getPropertyType() == Date.class) {
                    result.setRecommend(mainObj == null ? null : DateFormatUtils.format((Date) mainObj, "yyyy/MM/dd"));
                    result.setSource(minorObj == null ? null : DateFormatUtils.format((Date) minorObj, "yyyy/MM/dd"));
                } else {
                    result.setRecommend(mainObj == null ? null : mainObj.toString());
                    result.setSource(minorObj == null ? null : minorObj.toString());
                }
                if (field.getName().equals("organizationId")){
                    result.setFieldCode(field.getName());
                    result.setFieldName(EnumExcelField.getFieldValueNameByFieldValue(field.getName() != null ? field.getName() : ""));
                    result.setEqual(false);
                    Method writeMethod = field.getWriteMethod();
                    String json = JSONObject.toJSONString(result);
                    String methodName = writeMethod.getName();
                    Method resultWriteMethod = BeanUtils.findDeclaredMethodWithMinimalParameters(compareResult.getClass(), methodName);
                    resultWriteMethod.invoke(compareResult, json);
                    continue;
                }
                result.setFieldCode(field.getName());
                result.setFieldName(EnumExcelField.getFieldValueNameByFieldValue(field.getName() != null ? field.getName() : ""));
                result.setEqual(!isSame);
                Method writeMethod = field.getWriteMethod();
                String json = JSONObject.toJSONString(result);
                String methodName = writeMethod.getName();
                Method resultWriteMethod = BeanUtils.findDeclaredMethodWithMinimalParameters(compareResult.getClass(), methodName);
                resultWriteMethod.invoke(compareResult, json);
            }
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new ServiceException(e);
        }
        if (diffCount > 0) {
            return compareResult;
        }
        return null;
    }

    因为时间类型和Class对比完之后给实体类字段类型映射不上所以过滤一下

    private static boolean isIgnore(PropertyDescriptor field) {
        String[] ignoreField = {"uploadTime", "uploadId", "class", "createDate","thirdOperation","secondOperation"};
        return Arrays.asList(ignoreField).contains(field.getName());
    }

     

    展开全文
  • 众所周知,在使用DataAnnotations数据验证的时候,特别是针对同一个InputDto的多个属性进行对比的时候,例如起始日期不能大于结束日期,我们需要在Attribute中知道当前InputDto对象的类型和对象值,以便进行两个属性...
  • redis 存对象的方法对比

    万次阅读 2018-01-04 12:10:22
    问题背景:原来项目里面全部是直接redis存储对象的json数据,需要频繁序列化和反序列化,后来考虑更换项目中redis存储对象为hash对象存储,但是获取后不能方便set get操作,很是蛋疼,怎么才能解决这个问题...
  • C#内存释放几个方法对比: 而Close与Dispose这两种方法区别在于,调用完了对象的Close方法后,此对象有可能被重新进行使用;而Dispose方法来说,此对象所占有资源需要被标记为无用了,也就是此对象被销毁了...
  • (1)DOM与jquery获取节点对象的体现形式 var divdom = document.getElementById("parent"); alert("dom对象为:"+divdom); var divjquery = $("#parent"); alert("jqeury对象:"+divjquery); alert("jquery对象...
  • js对象的格式,JSON属性名必须有双引号,如果值是字符串,也必须是双引号; 二:JSON具体表示规则 对象是一个无序"名称/值对"集合, 一个对象用花括号{}括起来, 每个名称后面加上一个冒号...
  • 简单的对象属性值对比方法

    千次阅读 2016-02-21 23:16:52
    这段时间,小编忙于修改自己所...并且新的接口中传递的对象和旧的接口中传递的对象之间共同的参数值需要一致,但是小编看了看,新旧对象的属性个数都在50+,一个一个对比不是不行,尽管这样做确实提高了准确率,但...
  • 程序开发行业发展至今,在程序开发过程中诞生了面向过程开发编程思想与面向对象开发编程思想。两种编程思想都是十分优秀编程思想,不同编程思想适用于不同开发场景。今天我们就来看一下,面向过程和面向对象...
  • 面向对象 :把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题步骤中行为。 性能对比: 面向对象易维护、易复用、易扩展。 因为面向对象有封装、继承、...
  • 可迭代对象:使用 iter 内置函数可以获取迭代器的对象,如果对象实现了能返回迭代器的 __iter__ 方法,那么对象就是可迭代的,实现了 __getitem__ 方法,而且其参数是从零开始的索引,这种对象也可以迭代。...
  • Android-获取Bitmap对象的API效果差异对比
  • 面向对象和面向过程小小对比 面向过程和面向对象这两大编程思想各有优劣,需要辩证看待。 首先我们理解一下什么是面向过程,什么是面向对象。 面向过程:POP(Process-oriented programming) 面向过程就是分析出...
  • 1.OC中是不可以直接声明一个对象的,如:NSString a; 这样声明是不被允许。你可以这样声明:NSString *a; 这声明是一个指针,这样编译器会自动为它分配一块内存,不过你会发现此指针打印时候可能有值,这是...
  • 匿名对象的方案虽然达到了我们想要效果,但对比实体对象方案,又有什么不同呢,下面我们来对比一下: 数据传递性、复用性:-匿名对象:基本上属于一次性数据,无法整体传递,无法复用。+实体对象:传递性,...
  • 语言对比-对象模型

    2016-01-03 13:40:07
    c++对象模型 // test.cpp : 定义控制台应用程序入口点。 // #include "stdafx.h" #include &lt;iostream&gt; #include &lt;stdio.h&gt; using namespace std; class ClassAA{ ...
  • 1.git diff的对比对象的争议?实际代码测试+详细解释 (a)问题背景:我们在初步接触Git使用教程时,都会接触到git diff这个命令,当我们在网络上百度git diff更多用法时,很多博客都复制贴贴般地介绍:“git ...
  • var a; function machobj(obj,obj2){ a=0; matchobj2(obj,obj2); return a; } function matchobj2(obj,obj2){ if(!obj && typeof(obj)!="undefined" && obj!=0){ obj={};... ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,161
精华内容 5,664
关键字:

对比的对象