2016-02-29 18 views
0

在我的java程序中,我有一个映射,其中包含someID和MyClass类型的数据对象之间的关联。如何实现不对称等于功能?

ConcurrentMap<Integer, MyClass> a; 

我不太经常但经常检查一个“值”对象是否包含某个长变量b。由于我不知道将someId与其他Id相关联,因此无法通过地图访问它。 要做到这一点,我想使用的containsValue:

a.containsValue(otherId) 

为了实现这个目标我重写了哈希码和平等的功能。

@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不一定需要是地图的someID。

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

+0

等于已被定义,在这种情况下,你不能是对称其“忽略”的问题因为你不能修改“长”类。如果你的钥匙可以成为“长”,那么只需要长一点。 –

+0

尽可能地避免在Map上调用'containsValue',因为它是一个'O(n)'操作。 –

回答

4

您使用的是Java-8,它是不是很难写:

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

总之:不要试图用equals()来做到这一点。该方法的合同是它应该是对称的(以及自反性,传递性和其他一些属性)。请参阅Javadoc了解equals所需属性的完整说明。

Java API(更一般地说)中的类被实现以期望该属性被保留,所以如果你故意违反合同,可能会意外地表现出来。

为您的类添加一个明确用于测试此不对称属性的新类。 compareAssymetrically

2

的问题与您equals实现是一个Long例如lMyClass例如mm.equals(l)可能返回true,而l.equals(m)总是会返回false,因为你不能改变Long的实施equals

如果您使用的是使用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); 
} 
+0

我相信你的答案在技术上是对我的问题和走向的正确答案。我接受了塔吉尔的回答,因为那正是我现在使用的。 – Jochen