Java 比较器不';无法在树集中处理对象类型
我正试图借助一个带有自定义比较器的Java 比较器不';无法在树集中处理对象类型,java,comparator,treeset,xtend,Java,Comparator,Treeset,Xtend,我正试图借助一个带有自定义比较器的TreeSet来消除列表中的重复对象。 对于此代码: 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 Comp
TreeSet
来消除列表中的重复对象。
对于此代码:
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
}
}
类ASDF{
int i
传球
新(通行证p,国际通行证i){
this.ref=p
这个。i=i
}
公共静态def void main(字符串[]args){
val list=新树集(
新比较器{
覆盖比较(ASDF obj1、ASDF obj2){
if(obj1.ref==obj2.ref&&obj1.i==obj2.i){
返回0
}
返回1
}
}
)
val a1=新ASDF(新通道(“p1”),1)
val a2=新ASDF(新通道(“p2”),2)
val a3=新ASDF(新通道(“p3”),3)
val a4=新ASDF(新通行证(“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»']
}
}
班级通行证{
@访问者
串
新的(字符串s){
这个.s=s
}
}
控制台上的实际输出:[p1->1,p2->2,p3->3,p4->4,p1->1,p3->3]
控制台上的预期输出:[p1->1,p2->2,p3->3,p4->4]
为什么我在集合中又得到了p1
和p3
?我在比较器中哪里出错了
注意:这只是一个示例代码片段。在我的“真实”代码中,我无法覆盖equals
或hashcode
如果您违反比较器的约定,请不要期望树集
正常运行
也就是说,您未能使比较器对称:
如果您不关心(甚至不能定义)总排序,那么使用正确定义的hashCode()
和equals()
以及HashSet
会做得更好
如果无法重写这些属性(在编写时),请创建一个包含相关属性的Key
类,定义Key
的hashCode()
和equals()
并使用HashMap
。或者,键
可能只是一个包装器,它保存了对传递的引用,并从传递
字段派生出它的哈希代码和相等信息。如果您破坏了比较器
的契约,请不要期望树集
的行为正常
也就是说,您未能使比较器对称:
如果您不关心(甚至不能定义)总排序,那么使用正确定义的hashCode()
和equals()
以及HashSet
会做得更好
如果无法重写这些属性(在编写时),请创建一个包含相关属性的Key
类,定义Key
的hashCode()
和equals()
并使用HashMap
。或者,Key
可能只是一个包装器,它保存了对Pass
的引用,并从Pass
字段中派生出它的哈希代码和相等信息。您的问题是您违反了Comparator
的约定,即如果compare(a,b)
返回一个正整数,compare(b,a)
必须返回一个负整数。除了其他要求,如传递性比较。在您的实现中,您返回的0
或1
不符合此约定,因此TreeSet
当然不能正常工作。您的问题是违反了Comparator
的约定,即如果compare(a,b)
返回一个正整数,compare(b,a)
必须返回一个负整数。除了其他要求,如传递性比较。在您的实现中,您可以返回不符合此约定的0
或1
,因此TreeSet
当然不能正常工作。如何为Pass
实现适当的equals方法,然后使用obj1.ref.equals(obj2.ref)
而不是obj1.ref==obj2.ref
。尝试过了。没有更改。为什么不发布一些可编译的代码。obj1.ref==obj2.ref
。尝试.equals()
。对于Pass
如何实现适当的equals方法,然后使用obj1.ref.equals(obj2.ref)
而不是obj1.ref==obj2.ref
。尝试过了。没有更改。为什么不发布一些可编译的代码。obj1.ref==obj2.ref
。试试.equals()
。奇怪的是,OP并没有破坏传递性,因为他总是为不同的元素返回1,所以aa
保持不变。我知道,我刚才提到了它,所以他在重新实现比较器时会考虑到它。:-)奇怪的是,OP并没有破坏传递性,因为他总是为不同的元素返回1,所以aa
成立。我知道,我刚才提到了它,所以他在重新实现比较器时考虑了它。:-)
Pass p1 = new Pass("p1");
Pass p2 = new Pass("p2");
compare(p1, p2); // returns 1
compare(p2, p1); // also returns 1 - not good