我正在尝试使用带有自定义TreeSet
的{{1}}来清除列表中的重复对象。
对于此代码:
Comparator
控制台上的实际输出:[p1-> 1,p2-> 2,p3-> 3,p4-> 4,p1-> 1,p3-> 3]
控制台上的预期输出:[p1-> 1,p2-> 2,p3-> 3,p4-> 4]
为什么我在集合中再次获得class ASDF {
int i
Pass ref
new(Pass p, int i) {
this.ref = p
this.i=i
}
public static def void main(String[] args) {
val list = new TreeSet(
new Comparator<ASDF> {
override compare(ASDF obj1, ASDF obj2) {
if (obj1.ref == obj2.ref && obj1.i == obj2.i) {
return 0
}
return 1
}
}
)
val a1 = new ASDF(new Pass("p1"), 1)
val a2 = new ASDF(new Pass("p2"), 2)
val a3 = new ASDF(new Pass("p3"), 3)
val a4 = new ASDF(new Pass("p4"), 4)
list.addAll(
a1, a2, a3, a4
,
a1, a2, a3, a4
,
a1, a2, a3, a4
,
a1, a2, a3, a4
)
println(list.map['''«ref.s»->«i»'''])
}
}
class Pass {
@Accessors
String s
new (String s) {
this.s=s
}
}
和p1
? p3
在哪里出错?
注意:这只是一个示例代码段。在我的“真实”代码中,我无法覆盖Comparator
或equals
答案 0 :(得分:4)
If you break contract of the Comparator
, don't expect TreeSet
to behave correctly.
Namely, here you failed to make the comparator symmetric:
Pass p1 = new Pass("p1");
Pass p2 = new Pass("p2");
compare(p1, p2); // returns 1
compare(p2, p1); // also returns 1 - not good
If you don't care (or cannot even define) about total ordering, you'd do much better with a properly defined hashCode()
and equals()
and a HashSet
.
If you cannot override those (as you write), create a Key
class that will hold the relevant attributes, define Key
's hashCode()
and equals()
and use a HashMap<Key, Pass>
. Alternatively, Key
might be just a wrapper that holds a reference to Pass
and derives it's hash code and equals info from Pass
' fields.
答案 1 :(得分:1)
Your problem is that you violate the contract of Comparator
which says that if compare(a, b)
returns a positive integer, compare(b, a)
has to return a negative integer. Besides other requirements like transitive comparings. In your implementation you either return 0
or 1
which does not follow this contract, so the TreeSet
cannot work properly of course.