通用对象比较工具类-GeneralComparator


由于公司有同步数据的逻辑,涉及到对大批量数据的对比,选择性覆盖,需要对许多不同的数据Beans进行对比。

以前都是针对不同对象重写equals方法,面对大量不同值对象,需要重写很多,比较麻烦,而且重写equals方法大多也只是变量值进行比较。;

有看过别人写的一些,很多都很不理想。。So 一言不合就写个工具类


简单的逻辑

1、判断类型,基本类型、集合、对象分别处理;

2、基本类型直接判断,集合取出后再判断,对象则利用反射获取成员变量,递归取值;

3、没了

也许看起来两个对象判空的时候写的冗长,没有什么与或或者其他会让代码看起来简洁漂亮的写法;
但我觉得这样的朴素的写法可以让比较次数降到最低;

入口:传入两个值对象,并对属性进行分类

/**
     * 同为空/都不为空:true
     */
    public static boolean compareObject(Object head, Object tail) {
        if (head == null) {
            if (tail != null) {
                return false;
            } else {
                return true;
            }
        } else {
            if (tail == null) {
                return false;
            }
        }
        if (head.getClass() != tail.getClass()) {
            return false;
        }
        if (head.equals(tail)) {
            return true;
        }
        if (head.getClass() == String.class) {
            return head.equals(tail);
        } else if (head.getClass() == Integer.class) {
            return (int) head == (int) tail;
        } else if (head.getClass() == Boolean.class) {
            return (boolean) head == (boolean) tail;
        } else if (head.getClass() == Long.class) {
            return (long) head == (long) tail;
        } else if (head.getClass() == Double.class) {
            return (double) head == (double) tail;
        } else if (List.class.isAssignableFrom(head.getClass())) {
            return compareList((List) head, (List) tail);
        } else if (Map.class.isAssignableFrom(head.getClass())) {
            return compareMap(head, tail);
        }
        Field[] fields = head.getClass().getDeclaredFields();
        for (Field field : fields) {
//            Class
    
     cls = field.getType();
            Object o1 = getFieldValue(head, field);
            Object o2 = getFieldValue(tail, field);
            boolean result = compareObject(o1, o2);
            if (!result) {
                return false;
            }
            continue;
        }
        return true;
    }

获取field值

    private static Object getFieldValue(Object bean, Field field) {
        try {
            field.setAccessible(true);
            Object value = field.get(bean);
            return value;
        } catch (IllegalAccessException ace) {
            ace.printStackTrace();
            return null;
        }
    }

比较List :List中仍可存储类型的数据,所以使用compareObject方法来比较

private static boolean compareList(List head, List tail) {
        if (head == null) {
            if (tail == null || tail.isEmpty()) {
                return true;
            } else {
                return false;
            }
        } else {
            if (tail == null) {
                return head.isEmpty();
            }
        }
        if (head.isEmpty() && tail.isEmpty()) {
            return true;
        }
        if (head.size() != tail.size()) {
            return false;
        }
        for (int i = 0; i < head.size(); i++) {
            boolean result = compareObject(head.get(i), tail.get(i));
            if (!result) {
                return false;
            }
        }
        return true;
    }

比较Map:Map中没有存储其他类型,均为基本类型,所以就偷懒直接equals比较了

 private static boolean compareMap(Object head, Object tail) {
        if (head == null) {
            if (tail == null) {
                return true;
            } else {
                boolean isEmpty = ((HashMap) tail).isEmpty();
                if (isEmpty) {
                    return true;
                } else {
                    return false;
                }
            }
        } else {
            if (tail == null) {
                boolean isEmpty = ((HashMap) head).isEmpty();
                if (isEmpty) {
                    return true;
                } else {
                    return false;
                }
            }
        }
        HashMap
    
    
     
      srcMap = (HashMap) head;
        HashMap
     
     
      
       tarMap = (HashMap) tail;
        if (srcMap.keySet().isEmpty() && tarMap.keySet().isEmpty()) {
            return true;
        }
        if (srcMap.keySet().size() != tarMap.keySet().size()) {
            return false;
        }
        for (String key : srcMap.keySet()) {
            if (!tarMap.containsKey(key)) {
                return false;
            }
            Object vSrc = srcMap.get(key);
            Object vTar = tarMap.get(key);
            if (!vSrc.equals(vTar)) {
                return false;
            }
        }
        return true;
    }
     
     
    
    

到这以及可以满足绝大部分的数据类型了,而且不论你数据多复杂,嵌套有多深。
没有short、char等,因为项目中没有,集合使用List、Map,其他也没有使用,所有就没有加入;

需要注意:
Object    :    true  :  Null && Null
Set    :    true  :  Null && Null , Empty && Empty ,  Empty && Null
下面是测试用,基本覆盖每个分支

public class TestEquals {
    public static void main(String args[]) {
        School school1 = getTestBean(0);
        School school2 = getTestBean(1);
        long start = System.currentTimeMillis();
        boolean result = GeneralComparator.compareObject(school1, school2);
        long end = System.currentTimeMillis();
        System.out.print(result + " --- " + (end - start));
    }

    private static School getTestBean(int index) {
        School school1 = new School();
        school1.id = 3;
        if (index == 1) {
//            school1.id = 4;
        }
        ArrayList
   
   
    
     teacher1 = new ArrayList<>();
        Teacher t1 = new Teacher();
        t1.setTeakcherTitle("ma");
        if (index == 1) {
//            t1.setTeakcherTitle("mas");
        }
        if (index == 1) {
//            teacher1.add(t1);
        }
        teacher1.add(t1);
        school1.teacherList = teacher1;

        ArrayList
    
    
     
      list = new ArrayList
     
     
      
      ();
        list.add("list_1");
        list.add("list_2");
        list.add("list_4");
//        if (index == 1) {
//            list.add("list_4");
//        }
        school1.setSchsoolId(list);
//
        HashMap
      
      
       
        map1 = new HashMap
       
       
         (); map1.put("ma2", "2"); map1.put("ma3", "22"); if (index == 1) { // map1.put("ma3", "2d2"); } school1.map = map1; ArrayList 
         
         
           > arrayMap = new ArrayList<>(); arrayMap.add(map1); if (index == 1) { // map1.put("ma2d","s2"); // arrayMap.add(map1); } school1.arrayMap = arrayMap; return school1; } } class School { public int id; private ArrayList 
          
            schsoolId; public HashMap 
           
             map; public ArrayList 
            
              teacherList; public ArrayList 
              
              
                > arrayMap; public ArrayList 
               
                 getSchsoolId() { return schsoolId; } public void setSchsoolId(ArrayList 
                
                  schsoolId) { this.schsoolId = schsoolId; } } class Teacher { public String teakcherTitle; public String getTeakcherTitle() { return teakcherTitle; } public void setTeakcherTitle(String teakcherTitle) { this.teakcherTitle = teakcherTitle; } } 
                 
                
               
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值