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

发布于 2024-12-17 21:04:16 字数 1637 浏览 0 评论 0 原文

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

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

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

这是我的代码快照:

    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

谢谢。

I have two DTO need to be compared using (Arrays.equals), they are never be equals . Data in both DTO are equals as I review each attribute, some times its length equals , but Arrays.equals return false, I try to use Arrays.deepEquals the same problem exist but in some fields . I found some point when I debug :

1- hashcode method not the same in both DTO.
2- problems in attributes from String type.

my question is how can I test and detect which attributes are different.

Here is my code snap :

    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();

data snap :

    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

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

彻夜缠绵 2024-12-24 21:04:16

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

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

  • 请提供简短、独立且正确的示例。您的代码丢失了真实的输入数据。这是与下一点相加的:

  • 大多数 StackOverflow 读者都无法执行西班牙语、法语、德语等脚本中偶尔出现的特殊字符的任何操作。更不用说完整的阿拉伯语单词了。这大大减少了想要考虑你的问题的人数。

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

  • 使用 String.equals 比较 DTO 中的每个字符串对。
  • 必须进一步检查返回 false 但以相同方式显示的每一对:使用 NFC 将它们馈送到 java.text.Normailzer NFKC 并再次比较结果。
  • 如果现在结果确实可以比较,则说明存在 Unicode 编码问题。写下您的结果,准备一个新示例,并使用新的搜索短语挖掘该网站。

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

哦,我差点忘了:你说过

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

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

Some remarks but not a sollution:

  • Contrary to the title of your question not Arrays.equals is your problem but the output of ObjectOutputStream. And even that might not be true - it might be an Unicode encoding problem (see below).

  • Please provides a short, self contained and correct example. Your code misses the real input data. This is adds up with the next point:

  • Most readers of StackOverflow can't do anything the occasionally special character of spanish, france, german ... scripts. Let alone complete arabic words. This decimates the number of people who want to think about your problem considerably.

Finally something to the problem itself: Two different Unicode strings can be displayed in the same way due to the way Unicode allows combinations of characters. So a general advice is: Boil down your problem as far as possible.

  • Compare each string pair in you DTOs by with String.equals.
  • Each pair which returns false but is displayed in the same way must be examined further: Feed them to java.text.Normailzer using both NFC and NFKC and compare the results again.
  • If results do compare now, you have Unicode encoding problems. Write up your results, prepare a new exampls and dig this site with the new search phrases.

If this procedure does not work to solve your problem or to narrow downs your problem, then nevertheless provide the results from your examination by editing your question.

Oh, I nearly forgot: You stated

I have two DTO need to be compared using ...

You should think about what you really want to achieve and then decide how to do that. If you want to compare bytes, use the Arrays.equals. If you want to compare DTOs, then build your own compare method by comparing each field in the DTOs doing any fancy "normalization" here. A tool to help you with that might be Apache EqualsBuilder.

回首观望 2024-12-24 21:04:16

Arrays.equals(byte[],byte[]) 文档

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

因此,如果您希望字节数组包含一些差异,则您将无法成功比较它们。

如果您没有(或不想)控制对象的序列化方式,那么您可能可以使用某种Comparator

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 并实现您的自定义等于逻辑。

As stated in Arrays.equals(byte[],byte[]) documentation:

Two arrays are considered equal if both arrays contain the same number of elements, and all corresponding pairs of elements in the two arrays are equal. In other words, two arrays are equal if they contain the same elements in the same order.

So, you won't be able two compare your byte arrays successfully if you expect them to contain some differences.

If you don't have (or don't want to have) control over how your objects are getting serialized, then you can probably use some sort of 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;
  }
}

I realize that this is a bit dodgy, so here is another take on the problem.

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;
  }
}

Subclass ByteArrayOutputStream and implement your custom equals logic.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文