使用Arrays.equals的两个dto的java字节数组比较

时间:2011-11-26 09:07:28

标签: java arrays bytearray

我需要使用(Arrays.equals)比较两个DTO,它们永远不会是等号。 DTO中的数据等于我查看每个属性,有时长度等于,但Arrays.equals返回false,我尝试使用Arrays.deepEquals存在同样的问题,但在某些字段中。我在调试时发现了一些问题:

1-哈希码方法在两个DTO中都不一样 来自String类型的属性中的2-问题。

我的问题是如何测试和检测哪些属性不同。

这是我的代码快照:

    Boolean isEqual = false;
    ByteArrayOutputStream bStream = new ByteArrayOutputStream();
    ObjectOutputStream oStream;

    ByteArrayOutputStream bStream2 = new ByteArrayOutputStream();
    ObjectOutputStream oStream2;

    try {
        oStream = new ObjectOutputStream(bStream);
        oStream.writeObject(obj1);
        byte[] obj1ByteArray = bStream.toByteArray();

        oStream2 = new ObjectOutputStream(bStream2);
        oStream2.writeObject(obj2);
        byte[] obj2ByteArray = bStream2.toByteArray();
        System.out.println("Obj1>>" + obj1ByteArray.length);
        System.out.println("Obj2>>" + obj2ByteArray.length);
        isEqual = Arrays.equals(obj1ByteArray, obj2ByteArray);

        oStream.close();
        oStream2.close();

数据快照:

    Length
Obj1>>709
Obj2>>709
------------------------------------------------
Object 1
com.beshara.hr.core.interfaces.web.job.shared.structure.dto.JobDTO@1ab5140
59
test_job_5555555
-100
59
1
وظيفة تجريبية 6
وظيفة تجريبية 6أخري
10
10
10.0
وظيفة تجريبية الغرض من الوظيفة 6

--------------------------------
Object 2
com.beshara.hr.core.interfaces.web.job.shared.structure.dto.JobDTO@4cfc52
59
test_job_5555555
0
59
1
وظيفة تجريبية 6
وظيفة تجريبية 6أخري
10
10
10.0
وظيفة تجريبية الغرض من الوظيفة 6

谢谢。

2 个答案:

答案 0 :(得分:0)

Arrays.equals(byte[],byte[]) documentation中所述:

  

如果两个数组包含相同数量的元素,并且两个数组中所有相应的元素对相等,则认为两个数组相等。换句话说,如果两个数组包含相同顺序的相同元素,则它们相等。

因此,如果您希望它们包含某些差异,那么您将无法成功比较两个字节数组。

如果您没有(或者不希望)控制对象的序列化方式,那么您可以使用某种Comparator<byte[]>

public final class MyComparator implements Comparator<byte[]> {

  private static final int ATTR_START = 0;
  private static final int ATTR_END = 7;

  @Override
  public int compare(byte[] left, byte[] right) {
    if (left.length != right.length)
      return left.length - right.length;

    byte[] leftAttr = Arrays.copyOfRange(left, ATTR_START, ATTR_END);
    byte[] rightAttr = Arrays.copyOfRange(left, ATTR_START, ATTR_END);

    return Arrays.equals(leftAttr, rightAttr) ? 0 : -1;
  }
}

我意识到这有点狡猾,所以这是对问题的另一种看法。

public final class MyByteArrayOutputStream extends ByteArrayOutputStream {

  private static final int ATTR_START = 0;
  private static final int ATTR_END = 7;

  @Override
  public int hashCode() {
    // this can be implemented based on *your* attribute/attributes
    // and its/their location in the buffer too, like in equals just below
    return Arrays.hashCode(buf);
  }

  @Override
  public boolean equals(Object object) {
    boolean equals = false;
    if (object instanceof MyByteArrayOutputStream) {
      MyByteArrayOutputStream other = (MyByteArrayOutputStream) object;
      byte[] thisAttr = Arrays.copyOfRange(buf, ATTR_START, ATTR_END);
      byte[] otherAttr = Arrays.copyOfRange(other.buf, ATTR_START, ATTR_END);

      if (Arrays.equals(thisAttr, otherAttr)) {
        byte[] thisRest = Arrays.copyOfRange(buf, ATTR_END, buf.length);
        byte[] otherRest = Arrays.copyOfRange(other.buf, ATTR_END, buf.length);

        equals = Arrays.equals(thisRest, otherRest);
      }
    }
    return equals;
  }
}

子类ByteArrayOutputStream并实现自定义等于逻辑。

答案 1 :(得分:0)

一些评论但不是解决方案:

  • 与您问题的标题相反,Arrays.equals不是您的问题,而是ObjectOutputStream的输出。甚至可能不是这样 - 它可能是Unicode编码问题(见下文)。

  • 请提供short, self contained and correct example。您的代码错过了真实的输入数据。这与下一点相加:

  • StackOverflow的大多数读者无法做任何西班牙语,法国语,德语...脚本的偶然特征。更别说完整的阿拉伯语单词了。这大大减少了想要大量思考问题的人数。

最后解决问题本身:由于Unicode允许字符组合的方式,可以以相同的方式显示两个不同的Unicode字符串。所以一般的建议是:尽可能地解决你的问题。

  • 将DTO中的每个字符串对与String.equals进行比较。
  • 必须进一步检查返回false但以相同方式显示的每一对:使用java.text.NormailzerNFC将其提供给NFKC并再次比较结果
  • 如果现在比较结果,则会出现Unicode编码问题。写下你的结果,准备一个new exampls并用新的搜索短语挖掘这个网站。

如果此程序无法解决您的问题或缩小您的问题范围,那么请通过编辑您的问题来提供检查结果。

哦,我差点忘了:你说过

  

我需要使用两个DTO进行比较...

你应该考虑你真正想要实现的目标,然后决定 如何做到这一点。如果要比较字节,请使用Arrays.equals。如果你想比较DTO,那么通过比较DTO中的每个字段来构建你自己的比较方法,在这里进行任何花哨的“规范化”。可以帮助您的工具可能是Apache EqualsBuilder