我有一个带有自定义比较器的TreeSet,但remove()操作不起作用。 这是代码:
new TreeSet<>(new Comparator<Tile>(){
public int compare(Tile o1, Tile o2){
if(o1 == o2){
return 0;
}
if(o1.getValue() > o2.getValue()){
return 1;
}
return -1;
}
});
我认为,使用此比较器,副本定义为o1 == o2,de order基于getValue()升序。但有些事情是错的......什么?
答案 0 :(得分:3)
o1 == o2
这是比较对象引用,而不是值。您没有涵盖值相等的情况。假设调用getValue()
并不昂贵,我通常会跳过对象引用等式检查以使我的代码更简单。
public int compare(Tile o1, Tile o2){
if(o1.getValue() == o2.getValue()){
return 0;
}
if(o1.getValue() > o2.getValue()){
return 1;
}
return -1;
}
或者更简单:
public int compare(Tile o1, Tile o2){
return o1.getValue() - o2.getValue();
}
答案 1 :(得分:1)
您撰写compare
的方式并不符合该方法的合同。您必须满足的条件之一是:
sgn(compare(x, y)) == -sgn(compare(y, x)) for all x and y
但是您的compare
方法并不能满足这一条件,因为如果您有两个Tile
s x
和y
满足x != y
和{{} 1}}然后x.getValue() == y.getValue()
和compare(x, y)
都是compare(y, x)
。
如果您违反-1
的合同,则会收到无法预测的结果,
如果您希望compare
的两个实例只有在具有相同标识的情况下才被视为重复项,那么很难看出您如何能够满足上述条件,因此这将使用{{{ 1}}。相反,您可以使用Tile
来覆盖TreeSet
或HashSet
类equals
。如果您无法控制班级hashCode
,并且Tile
和Tile
已被覆盖,那么您可以使用equals
或番石榴&hashCode
视图#39; s keySet
。不幸的是,这些解决方案并没有对收集品进行分类。
如果您需要根据IdentityHashMap
返回的值对集合进行排序,并且您只想在实例完全相同时删除重复项,我认为没有任何明智的选择这样做的方式。您可以使用newIdentityHashSet()
使用getValue()
进行排序(与比较器返回ArrayList
一起使用)。每当你需要删除重复项时,你可以做这样的事情
Collections.sort