Java Hashmap将两个相同的对象分开存储

时间:2013-11-30 16:43:21

标签: java junit hashmap hashcode

我覆盖了一个类的hashCode和equals方法。我也为它编写了单元测试,它都是绿色的。当我用hashmap测试它时,我注意到一些奇怪的东西。 我创建了两个相同的对象:

obj1 = new PacmanVeld(field2);
obj2 = new PacmanVeld(field2);

我用这段代码测试了它:

Assert.assertTrue(obj1.hashCode() == obj2.hashCode()); //works
Assert.assertTrue(obj1.equals(obj2)); //works

HashMap<PacmanVeld, Integer> testMap = new HashMap<>();
testMap.put(obj1, 5);

Assert.assertTrue(testMap.put(obj2, 7) == 5); //fails throws nullpointerexception
Assert.assertTrue(testMap.get(obj1) == 7); //fails 

我不明白为什么这不起作用,因为据我所知,在HashMap的算法中,obj1和obj2是相同的对象。

PacmanVeld课程:

public class PacmanVeld
{
    private Node[][] nodes;

    public PacmanVeld(char[][] veld)
    {
        this.nodes = new Node[veld.length][veld[0].length];

        for (int i = 0; i < veld.length; i++)
        {
            for (int j = 0; j < veld[i].length; j++)
            {
                switch (veld[i][j])
                {
                    case '%':
                        nodes[i][j] = new Node(i, j, NodeType.WALL);
                        break;
                    case ' ':
                        nodes[i][j] = new Node(i, j, NodeType.EMPTY);
                        break;
                    case '.':
                        nodes[i][j] = new Node(i, j, NodeType.CRUMB);
                        break;
                    case 'P':
                        nodes[i][j] = new Node(i, j, NodeType.PACMAN);
                        break;
                }
            }
        }
        initFinish();
        initPacman();
    }

    //getters, setters & methods

    public boolean equals(PacmanVeld p)
    {
        if (p.nodes.length != nodes.length) { return false; }
        for (int i = 0; i < nodes.length; i++)
        {
            if (!Arrays.deepEquals(nodes[i], p.nodes[i])) { return false; }
        }
        return true;
    }

    @Override
    public int hashCode()
    {
        List<Node> nodeList = getNodeList();
        return Arrays.deepHashCode(nodeList.toArray());
    }

    private void initPacman()
    {
        for (Node[] rij : this.nodes)
        {
            for (Node n : rij)
            {
                if (n.isPacman())
                {
                    pacman = n;
                }
            }
        }
    }
}

3 个答案:

答案 0 :(得分:3)

问题是您没有覆盖从对象类中删除的equals()方法。

@Override
public boolean equals(Object o)
    {
        PacmanVeld p = (PacmanVeld)o;
        if (p.nodes.length != nodes.length) { return false; }
        for (int i = 0; i < nodes.length; i++)
        {
            if (!Arrays.deepEquals(nodes[i], p.nodes[i])) { return false; }
        }
        return true;
    }

答案 1 :(得分:0)

HashMap返回null以获取新值。您的Assert.assertTrue(testMap.put(obj2, 7) == 5);测试用例会引发NPE异常,因为obj2HashMap处被忽略。您可以使用已放入HashMap的obj1进行测试

  Assert.assertTrue(testMap.put(obj2, 7) == 5); 
                  //throws NPE because obj2 is not inserted

尝试使用obj1

  Assert.assertTrue(testMap.put(obj1, 7) == 5); 
          //will retrun true because, 5 is last inserted value with obj1
  Assert.assertTrue(testMap.put(obj1, 7) == 8); 
         // will retrun false because

答案 2 :(得分:0)

我无法重现您的错误。由于发布评论的时间太长,我会将其添加为答案,并在您展示HashCodeEquals实施后编辑我的帖子以解释您的错误。

public class Test {
    public static void main(String[] args) {
        Map<MyPersonalClass, Integer> map = new HashMap<>();
        MyPersonalClass obj1 = new MyPersonalClass();
        obj1.someInt = 5;
        obj1.someString = "test";

        MyPersonalClass obj2 = new MyPersonalClass();
        obj2.someInt = 5;
        obj2.someString = "test";

        System.out.println(obj1.equals(obj2));
        System.out.println(obj1.hashCode() == obj2.hashCode());

        map.put(obj1, 5);
        System.out.println(Arrays.toString(map.values().toArray()));

        System.out.println(map.put(obj2, 10) == 5);
        System.out.println(Arrays.toString(map.values().toArray()));
        System.out.println(map.get(obj1));
    }
}

class MyPersonalClass {
    public String someString;
    public int someInt;

    @Override
    public boolean equals(Object arg0) {
        if(arg0 == this) { return true; }
        if(!(arg0 instanceof MyPersonalClass)) { return false; }

        MyPersonalClass obj = (MyPersonalClass) arg0;

        return obj.someString.equals(this.someString) && obj.someInt == this.someInt;
    }

    @Override
    public int hashCode() {
        return this.someString.hashCode() * 37 + this.someInt;
    }
}

输出:

  


  真正
  [5]
  真正
  [10]
  10