java - 二维列表数组的问题

标签 java arrays list arraylist 2d

简而言之,我有一个名为 PersonList 的对象,它具有 Person 对象的列表。我创建了 PersonList 的 2D 数组来模拟 map ,并在该 map 中随机放置和移动 Person 对象。但是,我在从 PersonLists 的 2D 数组中删除 Person 时遇到问题。同时,似乎同一个 Person 永远不会被添加到 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; }
}

人员列表:

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

现在,我又多了一个类来控制一些 Person,并包含 PersonList 的 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的大小再次增加。我已经三次检查了我的 add 函数(这是一个简单的单行函数)并确保数组索引是正确的。怎么会发生这种事?

最佳答案

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

编辑:每当您重写equals()时,请确保重写hashCode()。缺少此功能可能会干扰 List 方法 remove()。其他人提到了这一点,但答案被删除了。

出于您的目的,hashCode() 应该只返回 id 假设这是唯一的。例如,不要将位置因素考虑在内 - 您希望一个成为一个身份,无论他们身在何处。对此进行测试,如果仍然无法正常工作,请更新您的问题。

关于java - 二维列表数组的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6836695/

相关文章:

java - 具有空列的结果集中的 Java Bean 是否会显着影响内存/大小?

java - 使用 Java 7 根据参数选择返回类类型

Java:如何在 JVM 加载类时拦截它们

Java String[] array = line.split ("") 其中 line 只是空格

c# - 将逗号分隔的字符串转换为 int[] 的最简单方法是什么?

python - 枚举 - Python 循环

python - 检查 python 列表中的成员资格问题

java - 如何使用 RxJava2 从无限 Stream<Integer> 创建 Observable<Integer>?

java - 合并两个文本文件并将其排序到第三个文件

python - 如何将dict的dict转换为指定格式的dict?