如何确定两个TreeSet对象是否相等?我使用OpenJDK-10。
ModifiebleObject
class ModifiebleObject implements Comparable<ModifiebleObject>{
Integer number;
String text;
@Override
public int compareTo(final ModifiebleObject o) {
return this.number - o.number;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (!(o instanceof ModifiebleObject)) return false;
final ModifiebleObject that = (ModifiebleObject) o;
return Objects.equals(number, that.number) &&
Objects.equals(text, that.text);
}
@Override
public int hashCode() {
return Objects.hash(number, text);
}
}SomeCode
SortedSet<ModifiebleObject> tree1 = prepare();
SortedSet<ModifiebleObject> tree2 = prepare(); //Returns cloned elements, so object references in tree1 and tree2 are different.
// ModifiebleObject implements Comparable<ModifiebleObject>
// compareTo does not use all the fields, just some of them.
//setSomeValueOutsideOfComparable sets value of the field, which is not used by compareTo
tree2.first().setSomeValueOutsideOfComparable("newValue");
boolean tree1EqualsTree2 = tree1.equals(tree2); //Returns true因为
TreeSet称AbstractSet.containsAll -> TreeSet.contains -> TreeMap.containsKey -> TreeMap.getEntry != null
TreeMap.getEntry使用紧致器或元素compareTo (元素实现可比较)。
有趣,但JavaDoc撒谎了!
java.utilTreeSet
/**
* Returns {@code true} if this set contains the specified element.
* More formally, returns {@code true} if and only if this set
* contains an element {@code e} such that
* {@code Objects.equals(o, e)}.
*
* @param o object to be checked for containment in this set
* @return {@code true} if this set contains the specified element
* @throws ClassCastException if the specified object cannot be compared
* with the elements currently in the set
* @throws NullPointerException if the specified element is null
* and this set uses natural ordering, or its comparator
* does not permit null elements
*/
public boolean contains(Object o) {
return m.containsKey(o);
}更正式地,返回{@code true}当且仅当此集合包含一个元素{@代码e},使得{@code Objects.equals(o,e)}。
但实际上它使用的是compareTo。
更新
我可以使用jdk或另一个库中的其他集合来保证唯一的元素和排序,并且等于为每个元素使用的另一个集合等于。
发布于 2019-02-08 12:24:43
TreeSet明确指出了这一点。这不是什么阴谋。
注意,如果要正确实现set接口,由一个集合(无论是否提供显式比较器)维护的排序必须与等于一致。(与平等一致的精确定义见可比或比较器)。这是因为set接口是按照等于操作定义的,但是一个TreeSet实例使用它的compareTo (或compare)方法执行所有元素比较,因此从Set的角度来看,这个方法认为相等的两个元素是相等的。一个集合的行为是明确的,即使它的顺序与相等不一致;它只是没有遵守set接口的一般契约。
你的班级忽视了Comparable,而你正在为此付出代价。
强烈建议使用
(x.compareTo(y)==0) == (x.equals(y)),但不是严格要求
发布于 2019-02-08 12:28:45
如果您有一组已定义的对象,那么您可以根据哈希码和等于方法覆盖哈希码和等于方法以及下面的方法比较。你可以用
org.apache.commons.collections
SetUtils.isEqualSet(set1, set2);或
org.apache.commons.collections
CollectionUtils.isEqualCollection(a, b)发布于 2019-02-12 19:02:04
这是一个对我有效的解决方案。
class TreeSetWithEquals extends TreeSet {
//Constructors which I will use
//
// I consider two sets equal if they have equal elements in the same order!
@Override
public boolean equals(Object o) {
//Check if Object not null, not the same reference as this, and
// it is instance of Set
//And their sizes are equal
//Iterate through boths sets and apply equals for each method.
}
}我为什么要这么做?在我们的代码中,我们为Idea ->中使用Objects.equals(this.field_i, that.field_i)的其他对象生成相等。我们懒得搜索代码中的位置并替换Objects.equals(this.field_i, that.field_i),如果field_i是一个排序集,则为一个util类,以检查集合的相等性。因此,更容易使用支持排序的集合,但对于this.equals中的每个元素使用this.equals。
有些人告诉我,eqauls,hashCode,compareTo必须是一致的。我同意eqauls的观点,hashCode必须是一致的。
例如。
enum WeaponType {
KNIFE,
HAND_GUN,
TWO_HANDED_GUN,
GRANADES, //To allow flash, smoke and fragmentation granades
DEFUSE_KIT
}
class Shooter {
// make sure we can have different weapons,
// but only one of type is allowed.
// Our tree set with such comparator will guarantee this requirement.
private SortedSet<Weapon> weapons = buyWeapons(andUseWeaponTypeComparator);为此,我将定义一个WeaponComparator
Comparator<Weapon> WEAPON_COMPARATOR = Compareator
.comparing(Weapon::getType, Comparator.naturalOrder()) //enum uses its element order.
}现在,如果你想持久化一个枪手并在卡夫卡向其他微服务发送消息,你将有equals来检查who send实体。
https://stackoverflow.com/questions/54592253
复制相似问题