【问题标题】:How can I implement asymmetric equals funciton?如何实现非对称等于函数?
【发布时间】:2016-06-12 08:12:18
【问题描述】:

在我的 java 程序中,我有一个映射,其中包含 someID 和 MyClass 类型的数据对象之间的相关性。

ConcurrentMap<Integer, MyClass> a;

不经常但经常,我必须检查“值”对象之一是否包含某个 long as 变量 b。由于我不知道 someId 与我的 otherId 的关联,因此我无法通过地图访问它。 为此,我想使用 containsValue:

a.containsValue(otherId)

为了实现这一点,我重写了 hashCode 和 equals 函数。

@Override
public boolean equals(Object o) {
    if ((o instanceof MyClass) && (((MyClass) o).someId().equals(this.someId()))) {
        return true;
    } else
    if ((o instanceof Long) && ((Long) o) == this.otherId) {
        return true;
    } else {
        return false;
    }
}

注意:代码中的otherId不一定是map的someID。

第一个 if 语句是对称的,第二个显然不是。我知道这不好,但是每次写一个循环也不好。 在this post 中,他们说不对称的等号将被忽略。如何让java忽略不对称问题?

【问题讨论】:

  • equals 根据定义必须是对称的,在这种情况下,您不能让它“忽略”问题,因为您不能修改 Long 类。如果您的密钥可以是 Long,只需将其设为 Long。
  • 尽可能避免在地图上调用containsValue,因为这是O(n) 操作。

标签: java equals


【解决方案1】:

如果你使用的是 Java-8,写起来并不难:

a.values().stream().anyMatch(myObj -> myObj.otherId() == wantedId);

【讨论】:

    【解决方案2】:

    简而言之:不要尝试使用equals() 执行此操作。该方法的约定是它应该是对称的(以及自反,传递并具有一些其他属性)。有关 equals 所需属性的完整说明,请参阅 Javadoc

    Java API(以及更普遍的)中的类被实现为期望此属性保持,因此如果您故意违反合同,可能会出现意外行为。

    为您的类添加一个新方法,该方法明确用于测试此不对称属性,例如compareAssymetrically.

    【讨论】:

      【解决方案3】:

      您的equals 实现的问题在于,对于Long 实例lMyClass 实例mm.equals(l) 可能返回true 而l.equals(m) 将始终返回false,因为您无法更改Longequals 的实现。

      如果您使用任何使用equalsArrayListHashMap 等...)的类,您将无法控制是否调用 m.equals(l)l.equals(m),因此您的代码可能不会像你希望它表现出来。

      如果您想检查Long 是否与MyClass 实例“相等”,请创建一个MyClass 实例,其otherId 等于Long,并比较这两个MyClass 实例.

      @Override
      public boolean equals(Object o) {
          if (o instanceof MyClass) { 
              MyClass m = (MyClass) o;
              if (m.someId().equals(this.someId())) {
                  return true;
              } else if (m.otherId == this.otherId) {
                  return true;
              } else {
                  return false;
              }
          } 
          return false;
      }
      
      public boolean equals(Long l) {
          MyClass m = new MyClass();
          m.setOtherId(l);
          return equals(m);
      }
      

      【讨论】:

      • 我相信您的回答在技术上是对我的问题的正确答案和前进的道路。我接受了 Tagir 的回答,因为这就是我现在正在使用的。
      猜你喜欢
      • 2019-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-19
      • 2018-12-20
      • 1970-01-01
      • 2019-07-27
      • 2013-01-25
      相关资源
      最近更新 更多