如何确定两个TreeSet
对象是否相等?我使用 open-jdk-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(元素实现Comparable)。
有趣,但是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 e}这样{@code Objects.equals(o,e)}时,返回{@code true}。
但实际上,它使用compareTo
。
我可以使用jdk或其他库中的其他哪个集合来保证元素的唯一性和排序,并且等于另一个集合中每个元素等于的使用。
答案 0 :(得分:2)
JavaDoc for TreeSet
明确地说了这句话。这不是阴谋。
请注意,集合维护的排序(无论是否显式 提供比较器)必须与equals 保持一致 正确实现Set接口。 (请参阅可比或比较器 才能精确定义与equals的一致性。) 因为Set接口是根据equals操作定义的, ,但是TreeSet实例使用其实例执行所有元素比较 compareTo (或比较)方法,因此两个元素被视为相等 从集合的角度来看,此方法是相等的。的 集合的行为是明确定义的,即使其顺序不一致 等于它只是不服从套装的总合约 界面。
您的课程忽略了the advice of Comparable
,您需要为此付费。
强烈建议,但并非严格要求
(x.compareTo(y)==0) == (x.equals(y))
答案 1 :(得分:2)
如果具有“已定义对象集”,则可以覆盖哈希码和equals方法,下面的方法将根据哈希码和equals方法进行比较。 您可以使用
org.apache.commons.collections
SetUtils.isEqualSet(set1, set2);
或
org.apache.commons.collections
CollectionUtils.isEqualCollection(a, b)
答案 2 :(得分:0)
这是对我有用的解决方案。
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.
}
}
我为什么要这样做?好吧,在我们的代码中,我们为使用Objects.equals(this.field_i, that.field_i)
的Idea->中的其他对象生成了相等值。我们很懒惰地在代码中搜索位置,如果Objects.equals(this.field_i, that.field_i)
是util类中的排序集,则替换field_i
来检查集合是否相等。因此,使用支持排序但在eqauls
中的每个元素上使用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.
}
现在,如果您想保留一个射手并将kafka中的消息发送给其他微服务,您将拥有equals
来检查谁是 Shooter 实体。