Java compareTo和TreeSet的问题

Java compareTo和TreeSet的问题,java,treeset,Java,Treeset,我在游戏中移除一个单位时遇到了问题。我正在做一个塔防游戏,这条路被分成不同的固定长度的区块。这些块知道其中的单位以及路径上的下一个块。当单元离开块的边界时,块将其从列表中删除,并将其添加到下一个块中 我用一个树状集合来记录块中单位的顺序,这样我就可以知道哪一个是路径上最远的。这些单位有一个位置字段,用于跟踪它们在路径上的距离,位置越高,它们就越远 在我的一些块中,我注意到当它试图从树集中移除一个单元时,移除返回false。我使用了一些断点,我可以看到单位实际上在树集合中,所以我认为我的问题是攻击

我在游戏中移除一个单位时遇到了问题。我正在做一个塔防游戏,这条路被分成不同的固定长度的区块。这些块知道其中的单位以及路径上的下一个块。当单元离开块的边界时,块将其从列表中删除,并将其添加到下一个块中

我用一个树状集合来记录块中单位的顺序,这样我就可以知道哪一个是路径上最远的。这些单位有一个位置字段,用于跟踪它们在路径上的距离,位置越高,它们就越远

在我的一些块中,我注意到当它试图从树集中移除一个单元时,移除返回false。我使用了一些断点,我可以看到单位实际上在树集合中,所以我认为我的问题是攻击单位的比较方法

以下是我的比较代码:

public int compareTo(Object other) {
    if (other != null && AttackingUnit.class.isAssignableFrom(other.getClass())) {
        AttackingUnit o = (AttackingUnit) other;
        int amount = position - o.position;
        if (amount != 0) {
            return amount;
        } else if (amount == 0 && this == o) {
            return 0;
        }
    }
    return 1;
}
我注意到问题所在的一个街区是一个街区,单位进入顶部,中途转弯,然后从右侧退出。该块有两个ArrayList,一个用于从上到下(enPath)的单位,另一个用于从左到右(exPath)的单位。下面是我遇到问题的代码:

for (int i = 0; i < exPath.size(); i++) {
    AttackingUnit unit = exPath.get(i);
    unit.stepX();
    if (unit.getX() > rightX) {
        nextBlock.addUnit(unit);
        units.remove(unit);
        exPath.remove(unit);
        i--;
    }
}
for(int i=0;irightX){
nextBlock.addUnit(单位);
单位。移除(单位);
h.移除(单元);
我--;
}
}

单位为exPath和units(树集),但units.remove(单位)返回false。关于如何将AttackingUnit上的compareTo更改为修复此问题,您有什么想法吗?

我看到的一个问题是您的
compareTo
是:

} else if (amount == 0 && this == o) {
您应该对它们进行ORing(或者去掉
this==o
check)。现在,具有相同位置的两个不同的
AttackingUnit
实例将返回为1(第一个较大)。这肯定会导致树集中的排序不一致

顺便说一下,您可以替换:

if (other != null && AttackingUnit.class.isAssignableFrom(other.getClass()))


这更容易阅读。

你的比较方法很奇怪。首先,您的列表中不应该有任何类型不正确的元素,也不应该有空元素,因为这会带来问题。因此,在这些情况下,您可以简单地抛出异常,而不是返回
1

第二,正如Steve已经指出的那样,
this==o
检查是不正确的-这违反了关系的对称性,给了您找不到元素的情况。这就提供了更简单的版本:

public int compareTo(Object other) {
    AttackingUnit o = (AttackingUnit) other;
    int amount = position - o.position;
    return amount;
}

第三,确保当一个单位在你的树集合中时,位置(即你的比较结果)不会改变。如果位置必须改变,首先从集合中删除元素,改变位置,然后再添加它。

我会给出一个例子,我的印象是,如果比较返回0,树集会考虑对象相同并且不添加该单元。我担心这一点,因为如果两个单位占用同一个空间,那么其中一个就不会添加到树中。如果需要两个位于同一位置的对象不同,则需要其他标准来区分它们,例如名称等。在这种情况下,不要简单地
返回1
,因为它不是对称的。我现在只有健康、x、y和位置字段。如果它们都相同,有没有一种方法可以获取java使用的变量ID,这样我就可以看到它们是否完全相同?如果不是,我可以用它来比较。我想你需要一个不同的数据结构。与其使用树集,不如尝试从一个位置到另一个位置的地图?这样你就可以在同一个位置有多个单位。我会考虑使用地图,但现在我已经让它工作了。我为单位添加了一个ID字段,并将compareTo的代码更改为。我还更改了移动单元的代码,以便它移除单元,然后在更改其位置后读取。这个现在很好用。
public int compareTo(Object other) {
    AttackingUnit o = (AttackingUnit) other;
    int amount = position - o.position;
    return amount;
}