[英]ArrayList.remove(Object o) not iterating over contents
So, I've been sitting on this problem for several hours now and I'm out of ideas. 因此,我已经在这个问题上坐了好几个小时了,但我没有主意。 I looked through the documentation (ArrayList and Object) and read a lot of Stackoverflow questions regarding
ArrayList.remove(Object obj)
, but nothing helped. 我浏览了文档(ArrayList和Object),并阅读了许多有关
ArrayList.remove(Object obj)
的Stackoverflow问题,但没有任何帮助。
I try to implement a simulation (game?) where I have a Cell[][] to store the map. 我尝试实现一个模拟(游戏?),在那里我有一个Cell [] []存储地图。 Each Cell has inhabitants (class Person) stored in an ArrayList, which move one step every iteration.
每个单元都有一个存储在ArrayList中的居民(Person类),该居民每次迭代都移动一个步骤。 When a Person moves I add them to the next Cell and remove them from the old one.
当一个人移动时,我将它们添加到下一个单元中,并将其从旧单元中删除。 Or rather try, as the remove part doesn't work yet.
还是尝试一下,因为删除部分尚不可用。
My Question: I need help implementing the ArrayList.remove(Object obj) method. 我的问题:我需要帮助来实现ArrayList.remove(Object obj)方法。
What I got so far: 我到目前为止所得到的:
class Cell
{
private final int x;
private final int y;
ArrayList<Person> inhabs = new ArrayList<Person>();
/** this method is called by a Person that wants to move to another Cell **/
public void moveMe(Person p){
try{
Cell northOfHere = grid.grid[y-1][x]//direction will be changed to be random
northOfHere.add(p);
}catch(ArrayIndexOutOfBoundsException ex){/*person falls from the edge of the world*/}
inhabs.remove(p); //this is not working right
}
public void add(Person p){
inhabs.add(p);
}
}
Class Person: 班级人员:
class Person extends Object
{
private int health;
private int strength;
private int food;
private final int nation;
@Override
public boolean equals(Object obj){
if(obj == null){return false;}
if(obj == this){return true;}
if(!(obj instanceof Person)){return false;}
Person p = (Person)obj;
return p.toString().equals(toString());
}
@Override
public int hashCode(){
return toString().hashCode();
}
@Override
public String toString(){
return String.format("Health: %03d, Strength: %03d, Food: %03d, Nation: %02d", health, strength, food, nation);
}
}
Some key points: 一些关键点:
inhabs.remove(p);
inhabs.remove(p);
is not working
false
. false
。 Person.equals(Object obj)
by the ArrayList always returns true because of the line if(obj == this){return true;}
. Person.equals(Object obj)
的第一次迭代始终返回true,这是因为if(obj == this){return true;}
。 I understand that this is a very specific question, however I could not find anything that adressed the problem of the ArrayList not even going over the Elements in it. 我知道这是一个非常具体的问题,但是我找不到任何解决ArrayList问题的东西,甚至没有遍历其中的Elements。
edit: more Code. 编辑:更多代码。 Probably irrelevant to the problem, but i'll post it anyway, for context.
可能与该问题无关,但出于上下文,我还是将其发布。
class Grid{
Cell[][] grid;
public Grid(Cell[][] in){
grid = in; //has some cells with people in it.
}
//simply iterates over all cells
public void tick(){
for(int y = 0; y<grid.length; y++){
for(int x = 0; x<grid[y].length; x++){
grid[y][x].tick();
}
}
}
class Cell
{
Grid grid;
public Cell(/*some constants constants*/ Grid g, ArrayList<Person> inh){
grid = g;
if(inh == null){
inhabs = new ArrayList<Person>();
}else{
inhabs = inh;
}
}
//tells every person to make a step
public void tick(){
for(Person p : inhabs.toArray(new Person[inhabs.size()])){
p.tick();
}
}
//and all the other methods from above, of course
}
class Person extends Object
{
Cell cell;
public Person(Cell c, int h, int s, int f, int n){
cell = c;
health = h;
strength = s;
food = f;
nation = n;
}
public void tick(){
//for testing, later more options
cell.moveMe(this);
}
//and all the other methods from above, of course
}
This can't be reproduced, here is a small test with your logic : 无法复制,这是您的逻辑测试:
public static void main(String args[]) {
Person p1 = new Person(10, 2, 2, 1);
Person p2 = new Person(10, 2, 2, 2);
Person p3 = new Person(10, 2, 2, 3);
List<Person> list = new ArrayList<Person>();
list.add(p1);
list.add(p2);
list.add(p3);
System.out.println(list.remove(p2)); //true
System.out.println(list.remove(p2)); //false
System.out.println(list.remove( new Person(10, 2, 2, 3))); //true
}
My guess is that you don't use the correct Person
, you either construct a new instance without giving every variables correctly. 我的猜测是您没有使用正确的
Person
,而是在没有正确给出每个变量的情况下构造了一个新实例。 (Note that you didn't provide the constructor here, with a final
value, this can't work...) (请注意,您未在此处为构造函数提供
final
值,因此无法使用...)
I have read your code. 我已经阅读了您的代码。 Your problem is simple.
您的问题很简单。
You tick
a Cell
that will tick
every Person
in that Cell
. 您
tick
一个Cell
,该Cell
将tick
该Cell
每个Person
。 From there you move that Person
from the current Cell
using Cell.moveMe(Person p);
从那里,您可以使用
Cell.moveMe(Person p);
从当前Cell
移动该Person
Cell.moveMe(Person p);
. 。 You do move the instance in the new
Cell.inhabs
and remove it from the current one. 您确实将实例移动到新的
Cell.inhabs
,并将其从当前实例中删除。 BUT since you have references of all your instance in both way, your Person
is never instructed to which Cell
it is moved ... so when you call : 但是由于您都以两种方式都引用了您的所有实例,因此永远不会指示您的“
Person
将其移动到哪个Cell
...因此,当您调用时:
public void tick(){
//for testing
cell.moveMe(this);
}
cell
is still the initial position... but that cell
don't hold that person, so it can't remove the instance received. cell
仍然是初始位置...但是该cell
无法容纳该人,因此它无法删除收到的实例。
A simple correction would be to return the cell where you move him into : 一个简单的更正是将您将其移至其中的单元格返回:
public Cell moveMe(Person p){
Cell northOfHere = null;
try{
northOfHere = grid.grid[y-1][x];
northOfHere.add(p);
}catch(ArrayIndexOutOfBoundsException ex){
System.out.println("fell from edge");/*person falls from the edge of the world*/
}
System.out.format("Remove from %s person %s%n", this, p);
System.out.println("removed: " + inhabs.remove(p));
return northOfHere;
}
And update that cell : 并更新该单元格:
public void tick(){
//for testing
cell = cell.moveMe(this);
}
I agreed here to keep cell
to null
when he "feel off the map", as it remain outside of any cell. 我同意在他“离开地图”时将
cell
保持为null
,因为它保留在任何单元格之外。
As Andy Turner pointed out, you need to fix the equals()
method. 正如Andy Turner指出的那样,您需要修复
equals()
方法。 In Person
class the equals()
must be precise. 在
Person
类中, equals()
必须精确。
There is a contract between hashCode()
and equals()
: if one object equals another, then their hashCode()
must be the same. hashCode()
和equals()
之间有一个约定 :如果一个对象等于另一个,则它们的hashCode()
必须相同。 So the easiest way is to piggyback equals()
too on toString()
: 因此,最简单的方法就是在
toString()
上也搭载equals()
toString()
:
class Person // automatically extends Object
{
// ...
@Override
public boolean equals(Object obj) {
return (obj instanceof Person) && // instanceof is null-safe
this.toString().equals((Person) obj).toString();
}
}
Honestly, I don't like writing equals()
and hashCode()
methods, unless absolutely necessary. 老实说,除非绝对必要,否则我不喜欢编写
equals()
和hashCode()
方法。 They are cumbersome and error-prone. 它们麻烦且容易出错。 In this case, it doesn't look absolutely necessary.
在这种情况下,它看起来并不是绝对必要的。 There are a few alternatives:
有几种选择:
EqualsBuilder
and HashCodeBuilder
. EqualsBuilder
和HashCodeBuilder
。 Here is a nice example. With HashCodeBuilder
you'd write code like this: 使用
HashCodeBuilder
您可以编写如下代码:
@Override
public int hashCode() {
return new HashCodeBuilder()
.append(this.health)
.append(this.strength)
...
.toHashCode();
}
With EqualsBuilder
you'd write code like this: 使用
EqualsBuilder
您可以编写如下代码:
@Override
public boolean equals(Object obj) {
if (obj instanceof Person == false)
{
return false;
}
if (this == obj)
{
return true;
}
Person that = (Person) obj;
return new EqualsBuilder()
.append(this.health, that.health)
.append(this.strength, that.strength)
...
.isEquals();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.