简体   繁体   English

2D列表列表的问题

[英]Problem with 2D array of lists

In short, I have an object called PersonList that has a List of Person objects. 简而言之,我有一个名为PersonList的对象,它有一个Person对象列表。 I have created a 2D array of PersonLists to simulate a map and randomly place and move Person objects within that map. 我创建了一个PersonLists的2D数组来模拟地图,并在该地图中随机放置和移动Person对象。 However, I'm having a problem removing Persons from the 2D array of PersonLists. 但是,我在从PersonLists的2D数组中删除Persons时遇到问题。 At the same time, it seems that the same Person will never be added to the same spot in the 2D array even if it moves there. 同时,似乎相同的Person永远不会被添加到2D阵列中的相同位置,即使它移动到那里。

I have tried my best to create a small version of what I have below. 我尽力创建我的下面的小版本。 I have a feeling I'm missing something glaring. 我有一种感觉,我错过了一些明显的东西。 I'm also open to ways I can implement this system better as this is probably the most inefficient way to do it. 我也很开心我可以更好地实现这个系统,因为这可能是最低效的方法。

Person :

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

Now, I have one more class that controls some Persons and contains the 2D array of PersonLists. 现在,我还有一个控制某些人的类,并包含PersonLists的2D数组。 It looks something like this: 它看起来像这样:

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

Imagine I kick off "Control.wander()" in a loop. 想象一下,我在一个循环中启动“Control.wander()”。 I'm having a problem where Persons are not being removed from the pmap correctly. 我有一个问题,人们没有正确地从pmap中删除人员。 I've printed off a grid with the size of each PersonList within pmap and the numbers will never decrease. 我打印了一个网格,其中包含pmap中每个PersonList的大小,数字永远不会减少。 However, they will not increase above the number of Persons in the "persons" list. 但是,他们不会超过“人员”名单中的人数。

That is, it seems like they cannot be removed, but no Person will be added to the same position in pmap more than once, even if they move there. 也就是说,它们似乎无法删除,但是不会有人将多次添加到pmap中的相同位置,即使它们移动到那里也是如此。

Is my problem immediately obvious, or should this theoretically work? 我的问题立即显而易见,还是理论上应该有效?

Feel free to ask any questions. 随意问任何问题。 Thanks for any help, I really appreciate it. 感谢您的帮助,我真的很感激。

EDIT : I've added some changes I made - I now use an iterator instead of a for-each loop and I have defined a simple hashCode method for Person. 编辑 :我添加了一些更改 - 我现在使用迭代器而不是for-each循环,我为Person定义了一个简单的hashCode方法。 As a test, I've added a method (getFirst()) in PlayerPos that returns the 0'th object in the list, or null if there isn't any. 作为测试,我在PlayerPos中添加了一个方法(getFirst()),它返回列表中的第0个对象,如果没有则返回null。

Within movePerson, I have something like: 在movePerson中,我有类似的东西:

System.out.println(p + " and " + pmap[src[0]][src[1]].getFirst());

And it expectantly prints two matching id's (I only use 1 person in my tests). 它期望打印两个匹配的id(我在我的测试中只使用1个人)。 I also added the same line within the remove(Person p) function itself in PersonList. 我还在PersonList中的remove(Person p)函数中添加了相同的行。 However, more often than not, this one will show null for the "getFirst()" result. 但是,通常情况下,此结果将为“getFirst()”结果显示null。 remove(Person p) is called immediately after my test in movePerson, so why would it return something there but nothing within PersonList itself? 我在movePerson中测试后立即调用remove(Person p),那么为什么它会在PersonList本身内返回一些内容但是什么都没有? Does this shed more light on my problem? 这是否更能说明我的问题? Thanks for all the help so far. 感谢目前为止所有的帮助。

EDIT 2 : I've also tried making PersonList's listPersons public and manipulating it directly, but I still seem to have the same problem. 编辑2 :我也尝试将PersonList的listPersons公开并直接操作它,但我似乎仍然遇到同样的问题。

EDIT 3 : With more testing, in movePerson, I've printed out the size of the src and dest pmap between every line, and it seems like it's being removed from the src pmap correctly, but after the add to the dest, the size of the src pmap increases again. 编辑3 :随着更多测试,在movePerson中,我已经打印出每行之间的src和dest pmap的大小,似乎它正在从src pmap中正确删除,但在添加到dest之后,大小src pmap再次增加。 I've triple checked my add function (it's a simple one-liner) and ensured that the array indices are correct. 我已经三次检查我的添加功能(它是一个简单的单线程)并确保数组索引是正确的。 How can this be happening? 怎么会发生这种情况?

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

should be 应该

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

So it looks like Persons were being added to a place other than where they thought they were. 因此看起来人们被添加到他们认为的地方以外的地方。

Also note that you shouldn't need to pass in src to the method, since Person already keeps track of where it is: 另请注意,您不需要将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]);
}

Edit: Make sure to override hashCode() whenever you override equals() . 编辑:确保在重写hashCode()时覆盖hashCode() equals() The absence of this may be interfering with the List method remove() . 缺少这可能会干扰List方法remove() Somebody else mentioned this but the answer was deleted. 有人提到这个,但答案被删除了。

For your purpose hashCode() should just return id assuming this is unique. 为了您的目的, hashCode()应该返回id假设这是唯一的。 Don't factor location into it for example - you want a Person to be one identity regardless of where they are. 例如,不要将位置考虑在内 - 您希望Person成为一个身份,无论他们身在何处。 Test this and then update your question if it's still not working. 测试这个,然后更新你的问题,如果它仍然无法正常工作。

Is your random method in PlacePersons intentionally commented out, or do you really want to place all Persons in [0, 0]. 你在PlacePersons的随机方法PlacePersons故意注释掉,或者你真的想要将所有人放在[0,0]中。
I don't think that the PersonList class is adding any value, I would have a structure as follows: 我不认为PersonList类正在添加任何值,我将有如下结构:
Map<Integer, Set<Person>>

The Integer key of the map would represent the y co-ordinate, and the position of Persons in the Set would represent their x co-ordinate. 地图的整数键代表y坐标,集合中人物的位置代表它们的x坐标。
You could choose whether to store each persons coordinate internally within the Person class whenever they are moved, or you could (at a cost) change getPos to iterate through the Map/Set until they locate themselves and return those co-ordinates. 你可以选择是否在移动时在Person类内部存储每个人的坐标,或者你可以(付费)改变getPos来迭代Map / Set直到他们找到自己并返回那些坐标。

Or even better Map<Person, Coord> where Coord is a class hold the xy co-ordinate position. 或者甚至更好的Map<Person, Coord> ,其中Coord是一个类,拥有xy坐标位置。

Remember to implement equals and hashCode properly for Person. 记得为Person正确实现equals和hashCode。

When using: 使用时:

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

You're obtaining a reference to Person p from your arrayList of persons and then using the symbolic reference generated by the foreach loop to move them. 您将从您的arrayList中获取对Person p的引用,然后使用foreach循环生成的符号引用来移动它们。 If you actually want to use the remove operation on your collection you need to set up an iterator. 如果您确实想在集合上使用remove操作,则需要设置迭代器。

See this for a good explaination 看到这个是一个很好的解释

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM