简而言之,我有一个名为 PersonList 的对象,它有一个 Person 对象列表。我创建了一个PersonLists的2D数组来模拟地图,并在该地图中随机放置和移动Person对象。但是,我在从PersonLists的2D数组中删除Persons时遇到问题。与此同时,似乎同一个人永远不会被添加到2D阵列中的相同位置,即使它移动到那里。
我已尽力创建下面的小版本。我有一种感觉,我错过了一些明显的东西。我也很开心我可以更好地实现这个系统,因为这可能是最低效的方法。
人:
public class Person {
private int id;
private int[] pos = new int[2];
public Person(int id) { this.id = id; }
public int getId() { return id; }
public int[] getPos() { return pos; }
public void setPos(int x, int y) { pos[0] = x; pos[1] = y; }
public boolean equals(Object obj) {
if (obj == null) { return false; }
if (obj == this) { return true; }
if (obj.getClass() != getClass()) { return false; }
Person rhs = (Person) obj;
return id == rhs.getId();
}
public int hashCode() { return id; }
}
PersonList :
import java.util.*;
public class PersonList {
List<Person> listPersons = new ArrayList<Person>();
PersonList() {}
public void add(Person p) { listPersons.add(p); }
public void remove(Person p) { listPersons.remove(p); }
public int getSize() { return listPersons.size(); }
}
现在,我还有一个控制某些人的类,并包含PersonLists的2D数组。它看起来像这样:
import java.util.*;
public class Control {
List<Person> persons = new ArrayList<Person>();
PersonList[][] pmap;
//numPeople is the number of Person objects to use
//size is the size of the pmap (used as both length and width)
public Control(int numPeople, int size) {
pmap = new PersonList[size][size];
//Initialize all PersonList objects within array
for(int y = 0; y < size; y ++) {
for(int x = 0; x < size; x ++) {
pmap[x][y] = new PersonList();
}
}
for(int i = 0; i < numPeople; i ++) {
persons.add(new Person(i));
}
// Defined below
placePersons();
}
// Randomly place Person on the pmap
private void placePersons() {
Iterator<Person> i = persons.listIterator();
while(i.hasNext()) {
Person p = i.next();
int x, y;
// Random method to obtain valid position within pmap stored in x and y
p.setPos(x, y);
pmap[x][y].add(p);
}
}
//Move person from "src" on pmap to "dest" on pmap
private void movePerson(Person p, int[] src, int[] dest) {
pmap[src[0]][src[1]].remove(p);
pmap[dest[0]][dest[1]].add(p);
p.setPos(dest[0], dest[1]);
}
//Makes every person wander around the pmap
public void wander() {
for(Person p : persons) {
int[] xy = new int[2];
// Random method to obtain valid position within pmap stored in xy
movePerson(p, p.getPos(), xy);
}
}
}
想象一下,我在循环中启动“Control.wander()”。我有一个问题,人们没有正确地从pmap中删除人员。我打印了一个网格,其中包含pmap中每个PersonList的大小,数字永远不会减少。但是,他们不会超过“人员”名单中的人数。
也就是说,它们似乎无法删除,但是不会有人将多次添加到pmap中的相同位置,即使它们移动到那里也是如此。
我的问题是否立即明显,或理论上应该有效吗?
随意提出任何问题。感谢您的帮助,我真的很感激。
编辑:我添加了一些更改 - 我现在使用迭代器而不是for-each循环,我为Person定义了一个简单的hashCode方法。作为测试,我在PlayerPos中添加了一个方法(getFirst()),它返回列表中的第0个对象,如果没有则返回null。
在movePerson中,我有类似的东西:
System.out.println(p + " and " + pmap[src[0]][src[1]].getFirst());
它期待打印两个匹配的id(我在我的测试中只使用1个人)。我还在PersonList中的remove(Person p)函数中添加了相同的行。但是,通常情况下,此结果将为“getFirst()”结果显示null。我在movePerson中测试后立即调用remove(Person p),那么为什么它会在PersonList本身内返回一些内容但是什么都没有?这是否更能说明我的问题?感谢目前为止的所有帮助。
编辑2 :我也尝试将PersonList的listPersons公开并直接操作它,但我似乎仍有同样的问题。
编辑3 :通过更多测试,在movePerson中,我已经打印出每行之间的src和dest pmap的大小,看起来它正在被正确地从src pmap中删除,但是在添加到dest之后,src pmap的大小再次增加。我已经三次检查我的添加功能(它是一个简单的单线程)并确保数组索引是正确的。怎么会发生这种情况?
答案 0 :(得分:2)
private void movePerson(Person p, int[] src, int[] dest) {
pmap[src[0]][src[1]].remove(p);
pmap[dest[0]][src[1]].add(p);
p.setPos(dest[0], dest[1]);
}
应该是
private void movePerson(Person p, int[] src, int[] dest) {
pmap[src[0]][src[1]].remove(p);
pmap[dest[0]][dest[1]].add(p); //fix on this line
p.setPos(dest[0], dest[1]);
}
所以看起来人们被添加到他们认为不在的地方。
另请注意,您不需要将src
传递给该方法,因为Person
已经跟踪它的位置:
private void movePerson(Person p, int[] dest) {
int[] pos = p.getPos();
pmap[pos[0]][pos[1]].remove(p);
pmap[dest[0]][dest[1]].add(p);
p.setPos(dest[0], dest[1]);
}
修改:每当您覆盖hashCode()
时,请务必覆盖equals()
。如果不这样做可能会干扰List
方法remove()
。有人提到这个,但答案被删除了。
出于您的目的,hashCode()
应该返回id
,假设这是唯一的。例如,不要将位置考虑在内 - 您希望Person
成为一个身份,无论他们身在何处。测试这个,然后更新你的问题,如果它仍然无效。
答案 1 :(得分:0)
您PlacePersons
中的随机方法是否有意注释掉了,或者您是否真的想将所有人放在[0,0]中。
我不认为PersonList类正在添加任何值,我将有如下结构:
Map<Integer, Set<Person>>
地图的整数键代表y坐标,集合中人物的位置代表x坐标。
您可以选择是否在移动时在Person类内部存储每个人坐标,或者您可以(需要付费)更改getPos
以迭代Map / Set直到他们找到自己并返回那些坐标
甚至更好Map<Person, Coord>
,其中Coord是一个持有x-y坐标位置的类。
请记住为Person正确实现equals和hashCode。
答案 2 :(得分:0)
使用时:
for(Person p : persons)
{
int[] xy = new int[2];
// Random method to obtain valid position within pmap stored in xy
movePerson(p, p.getPos(), xy);
}
您正在从您的arrayList中获取对Person p的引用,然后使用foreach循环生成的符号引用来移动它们。如果您确实想在集合上使用remove
操作,则需要设置迭代器。