如何实现非对称等于函数?
How can I implement asymmetric equals funciton?
在我的 java 程序中,我有一个映射,其中包含 someID 和 MyClass 类型的数据对象之间的相关性。
ConcurrentMap<Integer, MyClass> a;
我不经常但经常检查 "value" 对象之一是否包含某个 long 作为变量 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不一定是地图的someID。
第一个 if 语句是对称的,第二个显然不是。我知道这不好,但每次都写一个循环也不好。
在 this post 他们说不对称的 equals 将被忽略。如何让 java 忽略不对称问题?
简而言之:不要尝试使用 equals()
执行此操作。该方法的契约是它应该是对称的(以及自反、传递和具有一些其他属性)。有关 equals 所需属性的完整描述,请参阅 Javadoc。
类 在 Java API(以及更普遍的情况下)被实现为期望此 属性 成立,因此如果您故意违反,可能会出现意外行为合同。
向您的 类 添加一个新方法,该方法明确用于测试此不对称 属性,例如compareAssymetrically
.
您的 equals
实施的问题在于,对于 Long
实例 l
和 MyClass
实例 m
,m.equals(l)
可能 return true 而 l.equals(m)
将始终 return false
,因为您无法更改 Long
对 equals
的实现。
如果您使用任何使用 equals
(ArrayList
、HashMap
等...)的 类,您无法控制是否 m.equals(l)
或 l.equals(m)
被调用,因此您的代码可能不会按照您希望的方式运行。
如果要检查 Long
是否是 "equal" 到 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);
}
如果你用的是Java-8,写起来不是很难:
a.values().stream().anyMatch(myObj -> myObj.otherId() == wantedId);
在我的 java 程序中,我有一个映射,其中包含 someID 和 MyClass 类型的数据对象之间的相关性。
ConcurrentMap<Integer, MyClass> a;
我不经常但经常检查 "value" 对象之一是否包含某个 long 作为变量 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不一定是地图的someID。
第一个 if 语句是对称的,第二个显然不是。我知道这不好,但每次都写一个循环也不好。 在 this post 他们说不对称的 equals 将被忽略。如何让 java 忽略不对称问题?
简而言之:不要尝试使用 equals()
执行此操作。该方法的契约是它应该是对称的(以及自反、传递和具有一些其他属性)。有关 equals 所需属性的完整描述,请参阅 Javadoc。
类 在 Java API(以及更普遍的情况下)被实现为期望此 属性 成立,因此如果您故意违反,可能会出现意外行为合同。
向您的 类 添加一个新方法,该方法明确用于测试此不对称 属性,例如compareAssymetrically
.
您的 equals
实施的问题在于,对于 Long
实例 l
和 MyClass
实例 m
,m.equals(l)
可能 return true 而 l.equals(m)
将始终 return false
,因为您无法更改 Long
对 equals
的实现。
如果您使用任何使用 equals
(ArrayList
、HashMap
等...)的 类,您无法控制是否 m.equals(l)
或 l.equals(m)
被调用,因此您的代码可能不会按照您希望的方式运行。
如果要检查 Long
是否是 "equal" 到 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);
}
如果你用的是Java-8,写起来不是很难:
a.values().stream().anyMatch(myObj -> myObj.otherId() == wantedId);