为什么 Treeset<Object> contains() return false 即使 Object.equals() 和 Object.compareTo() 是一致的?
Why does Treeset<Object> contains() return false even if Object.equals() and Object.compareTo() are consistent?
我使用 TreeSet 对我正在开发的游戏引擎中的 Task
对象进行排序。我在Task
中写了compareTo()
方法,在我的自定义Comparator
中写了compare()
方法(只是为了尝试,因为它returns [=18=的值]) 然后我写了 equals()
(再次尝试)。
...
Treeset set;
Task t;
...
System.out.println(t.compareTo(set.first()));
System.out.println(set.comparator().compare(t, set.first()));
System.out.println(t.equals(set.first()));
System.out.println(String.valueOf(set.contains(t)));
如果我运行这个代码我得到这个输出:
0
0
true
false
我没有考虑到什么?
编辑:这里是 类。我 运行 输出测试而不是调用 queue.remove(t)
class TaskQueue {
private double taskTime;
private TreeSet<TimedTask> queue;
private ArrayList<TimedTask> toAddBuffer;
public TaskQueue(double taskTime) {
this();
this.taskTime = taskTime;
}
public TaskQueue() {
queue = new TreeSet<>(new Comparator<TimedTask>(){
@Override
public int compare(TimedTask o1, TimedTask o2) {
return o1.compareTo(o2);
}
});
toAddBuffer = new ArrayList<>();
}
public double getTaskTime() {
return taskTime;
}
public void setTaskTime(double taskTime) {
double delay = taskTime - this.taskTime;
this.taskTime = taskTime;
for (TimedTask t : queue) {
t.setTimeStamp(t.getTimeStamp() + delay);
}
}
public void add(TimedTask t) {
toAddBuffer.add(t);
}
private void add(TimedTask t, double millisecondDelay) {
t.setTimeStamp(t.getTimeStamp() + (millisecondDelay * (Game.TIME_SCALE)));
queue.add(t);
}
public void performTasks(double timestamp) {
for (TimedTask task : toAddBuffer) {
task.setTimeStamp(taskTime + task.getMilliseconds() * (Game.TIME_SCALE / 1000));
queue.add(task);
}
toAddBuffer.clear();
ArrayList<TimedTask> toRemoveBuffer = new ArrayList<>();
TimedTask taskToAdd = null;
boolean scheduledNew;
do {
scheduledNew = false;
for (TimedTask t : queue) {
if (timestamp < t.getTimeStamp()) {
taskTime = timestamp;
break;
}
t.perform();
toRemoveBuffer.add(t);
if (t.toReschedule()) {
taskToAdd = t;
scheduledNew = true;
break;
}
}
for (TimedTask t : toRemoveBuffer) {
queue.remove(t);
}
toRemoveBuffer.clear();
if (taskToAdd != null) {
add(taskToAdd, taskToAdd.getMilliseconds());
taskToAdd = null;
}
} while (scheduledNew);
}
}
public abstract class TimedTask extends Task implements Comparable<TimedTask> {
private double timeStamp;
private double milliseconds;
private boolean reschedule;
public TimedTask(double delay) {
this.milliseconds = delay;
}
double getTimeStamp() {
return timeStamp;
}
void setTimeStamp(double timeStamp) {
this.timeStamp = timeStamp;
}
public boolean toReschedule() {
if (milliseconds == 0.0) {
return false;
}
return reschedule;
}
public void setToReschedule(boolean toReschedule) {
reschedule = toReschedule;
}
public double getMilliseconds() {
return milliseconds;
}
public void setMilliseconds(double milliseconds) {
this.milliseconds = milliseconds;
}
@Override
public final int compareTo(TimedTask t) {
if (this == t) {
return 0;
}
if (timeStamp < t.timeStamp) {
return -1;
}
return 1;
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (!this.getClass().equals(o.getClass()))
return false;
TimedTask that = (TimedTask) o;
return this.compareTo(that) == 0;
}
}
@Override
public final int compareTo(TimedTask t) {
if (this == t) {
return 0;
}
if (timeStamp < t.timeStamp) {
return -1;
}
return 1;
}
这是完全错误的。它可以是 - 在你的例子中 - timeStamp == t.timeStamp
但 this != t
.
改为写
@Override
public final int compareTo(TimedTask t) {
return Integer.compare(timeStamp, t.timeStamp);
}
您必须覆盖方法 hashCode
和 equals
。如果您不知道如何实现在堆栈上查找或 google 它。
中包含检查方法hashCode
,如果为假,则equals
。
您对 compareTo
的实施是错误的。
if (this == t) {
return 0;
}
此检查对象是否与比较相同。
Foo foo1 = new Foo();
Foo foo2 = new Foo();
bollean result = foo1 == foo2;
以上总是错误的,因为 foo1 和 foo2 不是同一个对象。是平等的,但不一样。
总之 double
不是比较好的类型。更好的是使用 BigDecimal
.
我使用 TreeSet 对我正在开发的游戏引擎中的 Task
对象进行排序。我在Task
中写了compareTo()
方法,在我的自定义Comparator
中写了compare()
方法(只是为了尝试,因为它returns [=18=的值]) 然后我写了 equals()
(再次尝试)。
...
Treeset set;
Task t;
...
System.out.println(t.compareTo(set.first()));
System.out.println(set.comparator().compare(t, set.first()));
System.out.println(t.equals(set.first()));
System.out.println(String.valueOf(set.contains(t)));
如果我运行这个代码我得到这个输出:
0
0
true
false
我没有考虑到什么?
编辑:这里是 类。我 运行 输出测试而不是调用 queue.remove(t)
class TaskQueue {
private double taskTime;
private TreeSet<TimedTask> queue;
private ArrayList<TimedTask> toAddBuffer;
public TaskQueue(double taskTime) {
this();
this.taskTime = taskTime;
}
public TaskQueue() {
queue = new TreeSet<>(new Comparator<TimedTask>(){
@Override
public int compare(TimedTask o1, TimedTask o2) {
return o1.compareTo(o2);
}
});
toAddBuffer = new ArrayList<>();
}
public double getTaskTime() {
return taskTime;
}
public void setTaskTime(double taskTime) {
double delay = taskTime - this.taskTime;
this.taskTime = taskTime;
for (TimedTask t : queue) {
t.setTimeStamp(t.getTimeStamp() + delay);
}
}
public void add(TimedTask t) {
toAddBuffer.add(t);
}
private void add(TimedTask t, double millisecondDelay) {
t.setTimeStamp(t.getTimeStamp() + (millisecondDelay * (Game.TIME_SCALE)));
queue.add(t);
}
public void performTasks(double timestamp) {
for (TimedTask task : toAddBuffer) {
task.setTimeStamp(taskTime + task.getMilliseconds() * (Game.TIME_SCALE / 1000));
queue.add(task);
}
toAddBuffer.clear();
ArrayList<TimedTask> toRemoveBuffer = new ArrayList<>();
TimedTask taskToAdd = null;
boolean scheduledNew;
do {
scheduledNew = false;
for (TimedTask t : queue) {
if (timestamp < t.getTimeStamp()) {
taskTime = timestamp;
break;
}
t.perform();
toRemoveBuffer.add(t);
if (t.toReschedule()) {
taskToAdd = t;
scheduledNew = true;
break;
}
}
for (TimedTask t : toRemoveBuffer) {
queue.remove(t);
}
toRemoveBuffer.clear();
if (taskToAdd != null) {
add(taskToAdd, taskToAdd.getMilliseconds());
taskToAdd = null;
}
} while (scheduledNew);
}
}
public abstract class TimedTask extends Task implements Comparable<TimedTask> {
private double timeStamp;
private double milliseconds;
private boolean reschedule;
public TimedTask(double delay) {
this.milliseconds = delay;
}
double getTimeStamp() {
return timeStamp;
}
void setTimeStamp(double timeStamp) {
this.timeStamp = timeStamp;
}
public boolean toReschedule() {
if (milliseconds == 0.0) {
return false;
}
return reschedule;
}
public void setToReschedule(boolean toReschedule) {
reschedule = toReschedule;
}
public double getMilliseconds() {
return milliseconds;
}
public void setMilliseconds(double milliseconds) {
this.milliseconds = milliseconds;
}
@Override
public final int compareTo(TimedTask t) {
if (this == t) {
return 0;
}
if (timeStamp < t.timeStamp) {
return -1;
}
return 1;
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (!this.getClass().equals(o.getClass()))
return false;
TimedTask that = (TimedTask) o;
return this.compareTo(that) == 0;
}
}
@Override
public final int compareTo(TimedTask t) {
if (this == t) {
return 0;
}
if (timeStamp < t.timeStamp) {
return -1;
}
return 1;
}
这是完全错误的。它可以是 - 在你的例子中 - timeStamp == t.timeStamp
但 this != t
.
改为写
@Override
public final int compareTo(TimedTask t) {
return Integer.compare(timeStamp, t.timeStamp);
}
您必须覆盖方法 hashCode
和 equals
。如果您不知道如何实现在堆栈上查找或 google 它。
中包含检查方法hashCode
,如果为假,则equals
。
您对 compareTo
的实施是错误的。
if (this == t) {
return 0;
}
此检查对象是否与比较相同。
Foo foo1 = new Foo();
Foo foo2 = new Foo();
bollean result = foo1 == foo2;
以上总是错误的,因为 foo1 和 foo2 不是同一个对象。是平等的,但不一样。
总之 double
不是比较好的类型。更好的是使用 BigDecimal
.