【问题标题】:How to compare the data of two same Objects in Java如何在Java中比较两个相同对象的数据
【发布时间】:2013-12-20 23:06:34
【问题描述】:

我有课

            MyData 

及其对象

             myData 

在那个 MyData 类中.. 有多个字段

喜欢

           int id   

           String  name 

           String desc 

等等..

现在我有这个类的两个对象..

是否可以检查这两个对象的数据是否都相同,就像两个对象具有相同的 Id、相同的名称、相同的 Desc ...而不检查该对象的每个字段..(即没有自己检查每个对象的id,name,desc)因为这个对象有几十个字段。

我正在使用带有 GWT 的 JAVA

我遇到了一些实现..不确定这是否可行.valid

    private static String oldSequence = "";

    boolean changed(TestSequence sequence) {
        String newSequence = serializeToString(sequence);
        boolean changed = !newSequence.equals(oldSequence);
        oldSequence = newSequence;
        return changed;


    }

    private static byte[] serialize(Object obj) throws IOException {
        ByteArrayOutputStream b = new ByteArrayOutputStream();
        ObjectOutputStream o = new ObjectOutputStream(b);
        o.writeObject(obj);
        return b.toByteArray();
    }

    private static String serializeToString(Object obj) {
        try {
            return new String(serialize(obj));
        } catch (Exception ex) {
            return "" + ex;
        }
    }

谢谢

【问题讨论】:

  • 您的编辑完全改变了问题,最好作为不同的问题提出。

标签: java gwt


【解决方案1】:

如果您不想在添加新字段时添加更多代码,可以尝试遍历字段。

你说“Without checking each and every field of this object ..(i.e without checking the id,name,desc of Each object myself)”,我不知道你是不想检查每个字段是否相等,还是不想为每个字段写一个检查是否相等。我假设是后者,因为您尝试通过使用字节检查来添加相等比较方法。

无论如何,检查每个字段的代码如下。您可以复制/粘贴到任何对象。如果将来您希望某些字段被检查而某些字段不被检查,您可以使用annotations

 @Override
 public boolean equals(Object o) {
     if (this == o) return true;
     if (o == null || getClass() != o.getClass()) return false;

     MyData myData = (MyData) o;

     Field[] fields = this.getClass().getDeclaredFields();
     for(Field field:fields){
         Object o1 = null;
         Object o2  = null;
         try {
             o1 = field.get(this);
             o2 = field.get(o);
         } catch (IllegalAccessException e) {
           return false;
         }
         if(o1 == null && o2 != null) return false;
         if(o2 == null && o1 != null) return false;
         if(o2 == null && o1 == null) continue;

         if(!o2.equals(o1)) return false;
     }

     return true;

}

【讨论】:

  • 这个实现部分正确;考虑让另一个类从这个类派生一些额外的字段,在这种情况下它将无法正常工作:)
【解决方案2】:

常规方法是覆盖equalshashCode 方法。 Java 标准库,例如 Map s、List s、Set s 使用 equals 和 hashCode 函数进行相等性测试。下面的代码也是空安全的;

这是您案例的代码;

    public class MyData {
    int id;

    String name;

    String desc;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        MyData myData = (MyData) o;

        if (id != myData.id) return false;
        if (desc != null ? !desc.equals(myData.desc) : myData.desc != null) return false;
        if (name != null ? !name.equals(myData.name) : myData.name != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (desc != null ? desc.hashCode() : 0);
        return result;
    }
}

您可以通过以下方式测试相等性;

....
Mydata d1 = new...
Mydata d2 = new...
boolean areTheyEqual = d1.equals(d2);

但是,如果不允许逐个字段进行比较,则可以使用字节数组,无需将它们转换为字符串。

    .....
    public boolean equals(Object other){
        if (this == other) return true;
        if (other == null || getClass() != other.getClass()) return false;
        byte[] bytesThis = serialize(this);
        byte[] bytesOther = serialize(other);
        if(bytesOther.length != bytesThis.length) return false;
        return Arrays.equals(bytesThis, bytesOther);
    }

    public static byte[] serialize(Object obj) throws IOException {
        ByteArrayOutputStream b = new ByteArrayOutputStream();
        ObjectOutputStream o = new ObjectOutputStream(b);
        o.writeObject(obj);
        return b.toByteArray();
    }
    ...

【讨论】:

    【解决方案3】:

    您应该重写 hashCode()equals() 方法。您可以从 IDE 生成这些。

     @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof MyData)) return false;
    
        MyData myData = (MyData) o;
    
        if (id != myData.id) return false;
        if (!desc.equals(myData.desc)) return false;
        if (!name.equals(myData.name)) return false;
    
        return true;
    }
    
    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result + name.hashCode();
        result = 31 * result + desc.hashCode();
        return result;
    }
    

    现在您可以比较对象。就是这样。

    【讨论】:

    • 这不是安全的实现。如果和的字符串为空怎么办?!
    • @hevi 如果有人想在这里比较空对象。你可以使用一些验证。顺便说一句,这里比较空对象的原因是什么?
    • @Ruhchira 某些字段可能故意为空,这会破坏您的解决方案。
    【解决方案4】:

    就像其他人所说的那样,您应该重写 equals()hashCode() 方法。

    请注意,您不必手动执行此操作。在 Eclipse 中,您只需单击 Source/generate hashCode() and equals(),它就会为您完成工作。我相信其他 IDE 也有类似的功能。

    【讨论】:

      【解决方案5】:

      GWT 不会影响您的要求。

      没有直接的方法。

      你必须定义你的相等性来检查天气它们是否相等。那是覆盖 equals() 方法。

      @Override
      public boolean equals(Object obj) { ...
      

      做之前:Right way to implement equals contract

      【讨论】:

        【解决方案6】:

        覆盖 hashCode()equals() 方法

        hashCode()

        此方法提供对象的拥有代码。

        基本上,Object 提供的hashCode() 的默认实现是通过将内存地址映射到一个整数值来派生的。如果查看 Object 类的源代码,你会发现 hashCode 的代码如下。

        public native int hashCode();
        

        表示hashCode是原生实现,在一定程度上提供了内存地址。但是,可以在您的实现类中覆盖 hashCode 方法。

        等于()

        此方法用于在两个对象之间进行相等比较。 Java中有两种类型的比较。一个是使用“= =”运算符,另一个是“equals()”。我希望你知道这两者之间的区别。更具体地说,.equals() 指的是等价关系。所以从广义上讲,你说两个对象是等价的,它们满足equals() 条件。

        【讨论】:

          【解决方案7】:

          序列化您的对象并比较结果!

          您应该明智地选择序列化方法。

          【讨论】:

          • 你能举个小例子吗
          【解决方案8】:

          覆盖MyData中对象的equals方法,独立检查字段。

          【讨论】:

            【解决方案9】:

            没有。

            您必须重写 equals() 方法并比较其中的对象。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-10-02
              • 1970-01-01
              • 2019-05-29
              • 2012-12-12
              • 1970-01-01
              • 1970-01-01
              • 2020-12-29
              • 1970-01-01
              相关资源
              最近更新 更多