gpt4 book ai didi

java - Treeset.contains() 问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:05:36 26 4
gpt4 key购买 nike

所以我已经为一个问题苦苦挣扎了一段时间,我想我不妨在这里寻求帮助。

我正在将 Ticket 对象添加到 TreeSet,Ticket 实现 Comparable 并覆盖了 equals()、hashCode() 和 CompareTo() 方法。我需要使用 contains() 检查对象是否已经在 TreeSet 中。现在,在向集合中添加 2 个元素后,一切正常,但在添加第三个元素后,它变得一团糟。

在将第三个元素添加到 TreeSet 后运行这段代码,Ticket temp2 是我正在检查的对象 (verkoopLijst)。

    Ticket temp2 = new Ticket(boeking, TicketType.STANDAARD, 1,1);
System.out.println(verkoop.getVerkoopLijst().first().hashCode());
System.out.println(temp2.hashCode());

System.out.println(verkoop.getVerkoopLijst().first().equals(temp2));
System.out.println(verkoop.getVerkoopLijst().first().compareTo(temp2));
System.out.println(verkoop.getVerkoopLijst().contains(temp2));

返回这个:

22106622
22106622
true
0
false

现在我的问题是这怎么可能?

编辑:

public class Ticket implements Comparable{

private int rijNr, stoelNr;
private TicketType ticketType;
private Boeking boeking;


public Ticket(Boeking boeking, TicketType ticketType, int rijNr, int stoelNr){
//setters
}

@Override
public int hashCode(){
return boeking.getBoekingDatum().hashCode();
}

@Override
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
public boolean equals(Object o){
Ticket t = (Ticket) o;

if(this.boeking.equals(t.getBoeking())
&&
this.rijNr == t.getRijNr() && this.stoelNr == t.getStoelNr()
&&
this.ticketType.equals(t.getTicketType()))
{
return true;
}

else return false;

}

/*I adjusted compareTo this way because I need to make sure there are no duplicate Tickets in my treeset. Treeset seems to call CompareTo() to check for equality before adding an object to the set, instead of equals().


*/
@Override
public int compareTo(Object o) {
int output = 0;
if (boeking.compareTo(((Ticket) o).getBoeking())==0)
{
if(this.equals(o))
{
return output;
}
else return 1;
}
else output = boeking.compareTo(((Ticket) o).getBoeking());
return output;
}

//Getters & Setters

最佳答案

关于 compareTo契约(Contract)

问题出在你的compareTo .这是 the documentation 的摘录:

Implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y.

此处转载您的原始代码以供引用:

// original compareTo implementation with bug marked

@Override
public int compareTo(Object o) {
int output = 0;
if (boeking.compareTo(((Ticket) o).getBoeking())==0)
{
if(this.equals(o))
{
return output;
}
else return 1; // BUG!!!! See explanation below!
}
else output = boeking.compareTo(((Ticket) o).getBoeking());
return output;
}

为什么是return 1;错误?考虑以下场景:

  • 给定Ticket t1, t2
  • 给定t1.boeking.compareTo(t2.boeking) == 0
  • 给定t1.equals(t2)返回 false
  • 现在我们有以下两个:
    • t1.compareTo(t2)返回 1
    • t2.compareTo(t1)返回 1

最后一个后果是违反 compareTo契约(Contract)。


解决问题

首先,您应该利用 Comparable<T> 的事实是可参数化的通用类型。也就是说,而不是:

// original declaration; uses raw type!
public class Ticket implements Comparable

声明这样的东西会更合适:

// improved declaration! uses parameterized Comparable<T>
public class Ticket implements Comparable<Ticket>

现在我们可以写 compareTo(Ticket) (不再是 compareTo(Object) )。有很多方法可以重写它,但这里有一个相当简单的方法:

@Override public int compareTo(Ticket t) {
int v;

v = this.boeking.compareTo(t.boeking);
if (v != 0) return v;

v = compareInt(this.rijNr, t.rijNr);
if (v != 0) return v;

v = compareInt(this.stoelNr, t.stoelNr);
if (v != 0) return v;

v = compareInt(this.ticketType, t.ticketType);
if (v != 0) return v;

return 0;
}
private static int compareInt(int i1, int i2) {
if (i1 < i2) {
return -1;
} else if (i1 > i2) {
return +1;
} else {
return 0;
}
}

现在我们还可以定义equals(Object)compareTo(Ticket) 方面而不是相反:

@Override public boolean equals(Object o) {
return (o instanceof Ticket) && (this.compareTo((Ticket) o) == 0);
}

注意 compareTo 的结构: 它有多个 return陈述,但事实上,逻辑流程是相当可读的。还要注意排序标准的优先级是如何明确的,并且如果您有不同的优先级,可以轻松重新排序。

相关问题

关于java - Treeset.contains() 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3432772/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com