如何快速高效地检查两个Java对象是否深度相等?

6

我有两个Java对象,它们都有一个大小在百万级别的byte[]字段。如何以最快、最有效的方式检查这两个Java对象是否深度相等?

实体示例:

@Entity
public class NormalBook
{

  @Id
  private String bookId;

  @Column
  private String title;

  @Column
  private byte[] pdfFile;

  //setters and getters

  }

注意:我正在为一个ORM工具做这个,基本上我正在检查一个处于托管状态的对象与持久化上下文中存在的对象。

4
如果您进行多个比较,最好为每个比较计算一个校验和/哈希码。 - biziclop
@Paul 这不是针对关系型数据库,而是针对NoSQL数据库。 - Dev
然而,这样做似乎需要将整本书的内容加载到ORM中。为什么要那样做呢?为什么不只是在磁盘上存储文件的相对路径呢? - Paul
如果这样的话,如果你在数据库中也存储文件的校验和,那么你将会节省很多麻烦。 - biziclop
是的。但我们仍然不知道为什么OP想要检查两本书的内容(即字节)是否相同。或者,即使这只是试图在不必要地存储内容的对象上实现相等性的产物,当它不需要时(至少不通过ORM)。 - Paul
显示剩余6条评论
3个回答

2

覆盖equals()或者有一个* helper方法(糟糕的选择!)并按照以下5个步骤进行:

1. Check for *not null*.
2. Check for same *type*.
3. Check for *size of byte[]*.
4. Check for `==` (*reference equality* of byte[]) 
5. Start comparing byte values 

如果我比较字节值(步骤4),你不觉得对于一个大对象来说会花费很多时间吗? - Dev
2
@dev 当然,时间将与对象大小成比例。除了实际比较之外,您还有什么其他选项可以进行比较呢? - xlecoustillier
1
@dev - 好的,如果你想检查value,那么你就必须这样做 :)。Arrays.equals()将涵盖步骤3、4和5。 - TheLostMind

0
在您的对象类的equals()定义中使用以下内容:
java.util.Arrays.equals(bs1, bs2)

你可能还想先检查它们是否是同一个数组(实例)。虽然这种方法可能已经做到了。

例如(并对包含数组的类进行一些假设):

public boolean equals(Object obj) {
    if(this == obj)
        return true;
    if(!(obj instanceof MyObject)) // covers case where obj null, too.
        return false;
    return Arrays.equals(this.bytes, ((MyObject)obj).bytes);
}

如果您的类中还有其他字段,您的equals()方法也应该考虑到这些字段。
(如果您能提供有关数组中存储的数据类型的更多信息,可能会有更好的答案。)

是的,Arrays.equals() 首先检查引用。 - TheLostMind
我正在将一个大小为20 MB的jar文件保存到byte[]中。 - Dev
1
@dev 为什么要将一个 jar 文件保存在 byte[] 中... 这样做的目的是什么? - sgpalit
你是否正在尝试检查两个JAR文件是否“相等”(即,按字节完全相同)? - Paul

0
如果你的类有像 byte[] 这样的字段,你可以使用类似以下的代码:
public class MyClass {


    byte[] a;

    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        MyClass other = (MyClass) obj;
        if (!Arrays.equals(a, other.a))
            return false;
        return true;
    }


}

如果您关心性能并可以确保一个唯一的hascode(这很重要,hascode需要是唯一的),那么您可以直接比较hascode


1
好的观点。当你重写equals()时,也应该始终实现hashCode() - Paul
你如何确保唯一的哈希码?一般来说,你无法做到。 - user253751
1
然而,哈希码(在Java中)不需要是 - 通常也不是 - 唯一的。(它们不是ID。)顺便说一句:我曾经花了两个星期来修复一个由某人编写的系统,他错误地认为哈希码总是唯一的。hashCode()返回值应该是良好分布的。Effective Java(Joshua Bloch)提供了一个很好的总结,说明何时以及如何重写hashCode() - Paul

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