【问题标题】:Equality between 2 HashMap2 HashMap 之间的相等性
【发布时间】:2011-05-04 04:52:09
【问题描述】:

在我的类的 equals() 方法中,我使用私有实例 HashMap 变量来比较相等性。但是,在比较它们的 HashMap 变量时,两个不同的对象仍然显示相等。进一步的研究将我带到了链接:Link Here。但是,它只是说 HashMap1.equals(HashMap2) 不起作用的原因是因为“如果不编写自定义代码,显然无法测试 Java 的数组是否相等。”

我不明白这个原因。谁能指导我一个详细的原因?

【问题讨论】:

    标签: java hashmap equals


    【解决方案1】:

    Java 数组类型上的equals 方法等价于==,因为Java 数组“类”不会覆盖Object.equals

    如果您想“按值”比较数组,您需要使用适当的java.util.Arrays.equals(...) 方法,或者自己实现它。

    如果您的HashMap 使用数组作为键或值,那么它将调用数组的equals 方法来测试两个映射之间的键和/或值是否相同。这会使HashMap.equals 行为异常(从您的角度来看)。这就是链接文章所说的。但是,如果您使用数组作为键或值类,数组语义会影响HashMap 相等性。如果您不这样做,那么 HashMap::equals 应该会按预期工作。

    Map 类上的相等性的 javadocs 有点复杂,但它们基本上归结为获取两个条目集,比较它们的大小,然后执行 s1.containsAll(s2)。当然,这很昂贵,但它应该适用于正确实现 Map 接口的所有 Map 类。


    请注意,使用数组作为映射的键是一个坏主意,原因如下:

    1. 数组equalshashCode 的语义在大多数情况下对于HashMap 是错误的。对于大多数用例,您需要映射按值而不是对象标识来比较键。
    2. 数组是可变的。如果我们假设有解决 equals / hashcode 问题的方法,您可以仍然通过修改数组键来破坏映射的不变量。

    【讨论】:

      【解决方案2】:

      原生 Java 数组没有 .equals() 函数。因此,如果您的哈希图的值(或我想的键)是数组,则 HashMap.equals() 将失败。我怀疑它会依靠 Object.equals() 来检查这两个对象是否实际上是同一个对象。

      // something like this
      class Object {
        public boolean equals( Object o) {
          return this == o;
        }
      }
      

      您可以通过在容器上使用一些变体而不是数组 [] 来回避这个问题,因为容器有自己的 .equals(),它在容器的连续元素上调用 equals(),而不是简单地检查它们是否相同的参考。 Collection.equals 实现的代码可能类似于:

      public boolean equals(Object o) {
        // sets never equal lists and visa versa
        if (o instanceof MyCollectionSubclass) {
          Iterator myIterator = iterator();
          Iterator theirIterator = ((Collection)o).iterator();
          while (myIterator.hasNext() && theirIterator.hasNext()) {
            Object myObj = myIterator.next();
            Object theirObj = theirIterator.next();
            if (!myObj.equals(theirObj)) {
              return false;
            }
          }
          // at least one will be false or we wouldn't have left the above while loop
          return myIterator.hasNext() == theirIterator.hasNext();
        }
        // not our class
        return false;
      }
      

      这可能会产生一个真实的值比较,具体取决于您调用 equals() 时集合的内容所做的事情。

      【讨论】:

      • 数组继承自Object,实现与Object相同。
      • 我是这么想的,虽然我懒得去查。
      【解决方案3】:

      文章是对的。只要可以使用相同的方法比较键对象和值对象,就可以使用 equals() 方法安全地比较 Hashmap。在文章中,map 值是数组,没有按预期实现 equals()。使用 ArrayList 可以解决问题。

      【讨论】:

        【解决方案4】:

        如果不编写自定义代码,就无法测试 Java 的数组是否相等

        这只是一种复杂的说法,即 Java 数组不会覆盖 Object.equals()。因此,如果您使用equals()(这是所有集合类的equals 方法所做的)比较它们,您会得到“实例相等”,而不是“值相等”。

        这实际上只是 equals 工作方式不同的一个特例,具体取决于它是否被覆盖。

        【讨论】:

          猜你喜欢
          • 2013-04-24
          • 1970-01-01
          • 2017-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多