2011-05-08 64 views
1

我在TreeSet中从我正在处理的游戏中删除一个单元时遇到了问题。我正在制作一个塔防游戏,路径被分成不同长度的块。块知道它内部的单元和路径上的下一个块。当单位离开块的边界时,块将其从列表中移除并将其添加到下一个块。compareTo和TreeSet的问题

我正在使用TreeSet来跟踪块中单元的顺序,这样我就可以知道哪个单元沿着路径最远。这些单位有一个位置字段,用于跟踪他们所在的路径有多远,位置越高,位置越远。

在我的一些块中,我注意到当它试图从它的TreeSet中删除一个单元时,remove将返回false。我使用了一些断点,我可以看到该单元实际上在TreeSet中,所以我认为我的问题是我的攻击单位的compareTo方法。

这里是我的代码的compareTo:

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; 
} 

一个地方我注意到这个问题块是单位进入前一个块,拿一半的一角,并退出右侧。该块有两个ArrayLists,一个用于从上到下(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--; 
    } 
} 

单位为exPath和在单元(TreeSet中),但units.remove(单元)返回false。关于如何在AttackingUnit上修改compareTo来解决这个问题的任何想法?

回答

1

你的compareTo方法很奇怪。首先,你的列表中不应该包含任何不正确类型的元素,也不应该包含空元素,因为这样会产生问题。所以你可以简单地在这些情况下抛出异常,而不是返回1。其次,正如史蒂夫已经指出的那样,this == o检查是不正确的 - 这违反了你的关系的对称性,给你找不到你的元素的情况。这使这个简单的版本:

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

第三,保证位置(即您比较的结果),而单位是在TreeSet中不会改变。如果位置必须改变,首先从设置中删除元素,改变位置,然后再次添加。

+0

我给了这个镜头,我的印象是,如果compareTo返回0,TreeSet会认为这些对象是相同的,并且不会添加该单元。我很担心这个,因为如果两个单位占据相同的空间,那么这个单位就不会被添加到树中。 – Jonathan 2011-05-08 20:53:45

+0

如果你需要两个对象在相同的位置不同,你需要一些其他的标准来区分它们,比如名字等。在这种情况下,不要简单地返回1,因为它不是对称的。 – 2011-05-08 20:57:28

+0

我现在唯一拥有的单位是健康,x,y和位置。如果他们都是一样的有一种获得Java使用的变量ID的方法,所以我可以看到他们是否完全相同或不相同?如果他们不是,我可以用它来比较。 – Jonathan 2011-05-08 21:03:22

1

一个问题,我看到的是在你compareTo是:

} else if (amount == 0 && this == o) { 

你应该他们或运算(或摆脱this == o检查)。就像现在一样,具有相同position的两个不同的AttackingUnit实例将返回为1(第一个较大)。这肯定会给树集上的不一致排序。

顺便说一句,你可以替换:

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

if (other instanceof AttackingUnit) 

哪一个更容易阅读。