Java中两个对象之间的差异

4

我希望编写一个Java程序,用于查找两个不同实例的对象之间的差异。我已经使用equals()和comparator实现了它。但是我想要找到这些差异并以日志格式显示。

以下是我的程序:

public class A implements Comparator<A>{

private int id1, id2;

/* setters and getters for id1 and id2 */

     public boolean equals(Object arg0) {
    if (this.getClass() != arg0.getClass()) {
        return false;
        }

        if (((A) arg0).getId1() == this.id1 && ((A) arg0).getId2() == this.id2) {
        return true;
        }

        return false;
     }

 public static void main(String args[]) {

    A obj1 = new A();
    obj1.id1 = 10;
    obj1.id2 = 20;

    A obj2 = new A();
    obj2.id1 = 30;
    obj2.id2 = 20;

    /*
     * equals comparison
     */

    if (obj1.equals(obj2)) {
        System.out.println("EQUALS");
    } else {
        System.out.println("NOT EQUALS");
    }

}

请问有人能告诉我如何找出差异并以日志格式显示吗?
谢谢。

1
对于每个属性,进行比较。针对每个差异,记录日志。可以更容易地生成值的List<String>(或List<Object>),然后为每个元素使用通用比较器,或者使用List<KeyValuePair<String,String>>(或Map<String,Object>或其他)来包括属性信息等。 - user166390
你想比较每个对象的所有属性,还是只比较对象是否为不同实例?如果你想比较每个属性,请尝试这个示例;如果你想进行第二种比较,请使用hashCode() - Crazenezz
5个回答

2
为了实现Comparator<A>,您需要一个方法public int compare(A o1, A o2)。以下是一个这样的实现示例:
@Override
public int compare(A o1, A o2) {
    if (o1 == o2) {
        return 0;
    } else if (o1 == null) {
        return -1;
    } else if (o2 == null) {
        return 1;
    }
    if (o1.getId1() != o2.getId1()) {
        return o1.getId1() - o2.getId1();
    } else {
        return o1.getId2() - o2.getId2();
    }
}

然后你可以像这样使用它:
    if (obj1.compare(obj1, obj2) == 0) {
        System.out.println("EQUALS");
    } else {
        System.out.println("NOT EQUALS");
    }

通常情况下,更常见的做法是让另一个类实现Comparator<A>,而不是将其放在A本身中。


我认为你指的是compareTo方法。 - npinti
不,那应该在 Comparable<A> 接口中。 - Keppil
确实,你是正确的。我以前从未见过这种方法。谢谢 :) - npinti

1

您可以使用Java的反射来比较两个具有相同属性的Bean,这些Bean都有用于比较所有属性的getter方法。

public static void compareBeans(Object bean1, Object bean2, String... propertyNames)
          throws IntrospectionException,
          IllegalAccessException, InvocationTargetException {
        Set<String> names = new HashSet<String>(Arrays
            .asList(propertyNames));
        BeanInfo beanInfo = Introspector.getBeanInfo(bean1
            .getClass());
        for (PropertyDescriptor prop : beanInfo
            .getPropertyDescriptors()) {
          if (names.remove(prop.getName())) {
            Method getter = prop.getReadMethod();
            Object value1 = getter.invoke(bean1);
            Object value2 = getter.invoke(bean2);
            if (value1 == value2
                || (value1 != null && value1.equals(value2))) {
              continue;
            }

            System.out.println("Property = "+prop.getName() +" Value of been1 ="+value1 +" : Value of bean2 ="+value2);
          }
        }
      }

用法:

如果我比较两个具有nameage两个属性的Student类的bean,如下:

BeanComparator.compareBeans(new Student("Amita", 21), new Student("Amit", 23) , props);

输出:

Property = age Value of been1 =21 : Value of bean2 =23
Property = name Value of been1 =Amita : Value of bean2 =Amit

它也能用于子对象吗?例如,如果学生有地址列表,那么它也能比较它们吗? - Anand

0
你可以使用开源工具javers - https://github.com/javers/javers。 在Javers中,你可以找到方法compare(Object one, Object another),返回Diff。 Diff包含一系列的改变(引用添加、属性更改等)。

0
你可以更改你的equals方法,然后逐个比较每个属性。在每次比较时,记录下结果。以下代码应该可以工作:
@Override
public boolean equals(Object arg0) {
    if (this.getClass() != arg0.getClass()) {
        return false;
    }

    boolean same = true;
    //LOG: Comparing ((A) arg0).getId1() with this.id1
    if (((A) arg0).getId1() == this.id1) {
        //LOG: Property Id1 is the same for both: Value of Id1 = this.id1        
    }
    else {
        //LOG: Property Id1 is not the same. Source Id1 = ((A) arg0).getId1() , target Id1 = this.id1
        same = false;
    }

    if (((A) arg0).getId2() == this.id2) {
        //LOG: Property Id2 is the same for both: Value of Id2 = this.id2        
    }

    else {
        //LOG: Property Id2 is not the same. Source Id2 = (((A) arg0).getId2(), target Id2 = this.id2
        same = false;
    }

    //
    return same;
}

编辑:我不太明白你所说的“自己的比较器”是什么意思。如果你想要自己进行比较,你可以这样做:

public boolean areTheSame(Object arg1, Object arg2)
{
    if (arg1.getClass() != arg0.getClass()) {
        return false;
    }

    boolean same = true;
    //LOG: Comparing ((A) arg0).getId1() with arg1.id1
    if (((A) arg0).getId1() == arg1.id1) {
        //LOG: Property Id1 is the same for both: Value of Id1 = arg1.id1        
    }
    else {
        //LOG: Property Id1 is not the same. Source Id1 = ((A) arg0).getId1() , target Id1 = arg1.id1
        same = false;
    }

    if (((A) arg0).getId2() == arg1.id2) {
        //LOG: Property Id2 is the same for both: Value of Id2 = this.id2        
    }

    else {
        //LOG: Property Id2 is not the same. Source Id2 = (((A) arg0).getId2(), target Id2 = arg1.id2
        same = false;
    }

    //
    return same;
}

你可以将这段代码放在主类中,然后在需要的时候调用它,而不是重复写这些行:

if (obj1.equals(obj2)) {
    System.out.println("EQUALS");
} else {
    System.out.println("NOT EQUALS");
}

所以你只需要这样做:

if (areTheSame(obj1, obj2)) 
{
    System.out.println("They are equal");
}
else
{
    System.out.println("They are not equal");
}

谢谢您的回复。但是如果我想使用自己的比较器来检查差异,我该如何做?请给我建议。 - Dhruthi
@Dhruthi:equals方法在你的类A中被重写实现,不就是你自己的比较器吗? - npinti
嗨npinti,我有一个需求,需要使用我的自定义比较器找到两个相同实例的对象的差异,并在日志中显示结果(比较器必须接受两个任意对象并找到差异)。我已经使用equals()方法完成了这个任务。但是我不记得如何使用自己的比较器类。请给我建议。 - Dhruthi
@Dhruthi:我试图更改我的答案,这应该让你构建你自己的比较器来接收2个对象。另一方面,你可以将我提供的答案与Keppil提供的答案合并。 - npinti
@Dhruthi:我建议你提出另一个问题,因为你所问的似乎超出了这里的范围。此外,如果任何答案解决了你发布的问题,你应该标记任何你认为正确的答案。 - npinti
显示剩余4条评论

0
你可以使用 Apache Commons EqualsBuilder 来生成你的 equals() 方法。
给定一个类:
public class Person {
    private long id;
    private String firstName;
    private String lastName;
}

你的 equals 方法将会长成这样

public boolean equals(Object object) {
    if (!(object instanceof Person)) {
        return false;
    }
    Person rhs = (Person) object;
    return new EqualsBuilder()
        .appendSuper(super.equals(object))
        .append(firstName, rhs.firstName)
        .append(lastName, rhs.lastName)
        .isEquals();
}

或者如果你想使用反射来做这件事

public boolean equals(Object o) {
   return EqualsBuilder.reflectionEquals(this, o);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接