当我创建一个对象的新实例作为键时,Java HashMap.get()返回null

当我创建一个对象的新实例作为键时,Java HashMap.get()返回null,java,hashmap,Java,Hashmap,我正在制作一个电子表格应用程序,并使用HashMap将数据存储在单元格中。作为键,我使用一个Point类,它只有行数和列数。我遇到的问题是,如果我对一个新点使用HashMap.get(),它将返回一个空值 HashMap<Point, String> cache = new HashMap<Point, String>(); Point p1 = new Point(1,1); Point p2 = new Point(2,2); cach

我正在制作一个电子表格应用程序,并使用HashMap将数据存储在单元格中。作为键,我使用一个Point类,它只有行数和列数。我遇到的问题是,如果我对一个新点使用HashMap.get(),它将返回一个空值

    HashMap<Point, String> cache = new HashMap<Point, String>();
    Point p1 = new Point(1,1);
    Point p2 = new Point(2,2);
    cache.put(p1, "Test: 1,1");
    cache.put(p2, "Test: 2,2");

    int maxRow = 2;
    int maxCol = 2;
    for (int i = 1; i <= maxRow; i++) {
        for (int j = 1; j <= maxCol; j++) {
            System.out.print(cache.get(new Point(i,j)));
            if (j < maxCol) 
                System.out.print("\t");
            if (j == maxRow)
                System.out.println("");
        }
    }
我可能遗漏了一些明显的东西,但我自己找不到。另外,如果你碰巧知道是否有更好的数据结构来存储来自细胞的数据,我很想听听。
提前谢谢

默认情况下,
点的equals方法使用
=
即对象标识。因为Hashmap使用equals方法,所以它最终会使用
==
比较键,这将返回false,除非它是同一个对象


要解决此问题,请实现点的
equals
hashCode
方法,以便
point1.equals(point2)
在坐标相同时返回true

默认情况下,
点的equals方法使用
=
即对象标识。因为Hashmap使用equals方法,所以它最终会使用
==
比较键,这将返回false,除非它是同一个对象


要解决此问题,请实现点的
equals
hashCode
方法,以便
point1.equals(point2)
在坐标相同时返回true

要详细说明我上面的评论,您的Point类应该实现hashcode和equals,如下所示: (存在许多实现,只有一个有效) 假设实例的变量是
x
y

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Point point = (Point) o;

        if (x != point.x) return false;
        if (y != point.y) return false;

        return true;
    }

    public int hashCode() {
        int result = x;
        result = 31 * result + y;
        return result;
    }
否则,如果您不重写这些方法,
Object
的Javadoc很好地解释了您的问题:

As much as is reasonably practical, the hashCode method defined by
     * class {@code Object} does return distinct integers for distinct
     * objects. (This is typically implemented by converting the internal
     * address of the object into an integer, but this implementation
     * technique is not required by the
     * Java<font size="-2"><sup>TM</sup></font> programming language.)
     *
     * @return  a hash code value for this object.
     * @see     java.lang.Object#equals(java.lang.Object)
     * @see     java.lang.System#identityHashCode
     */
    public native int hashCode();
在合理可行的情况下,由
*类{@code Object}为distinct返回不同的整数
*对象。(这通常通过转换内部
*将对象的地址转换为整数,但此实现
*技术是不需要的
*JavaTM编程语言。)
*
*@返回此对象的哈希代码值。
*@see java.lang.Object#equals(java.lang.Object)
*@see java.lang.System#identityHashCode
*/
公共本机int hashCode();

因此,
新点(1,2)
将不会被视为等于
新点(1,2)
,因此,永远无法从
地图中检索到

要详细说明我上面的评论,您的Point类应该实现hashcode和以下等式: (存在许多实现,只有一个有效) 假设实例的变量是
x
y

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Point point = (Point) o;

        if (x != point.x) return false;
        if (y != point.y) return false;

        return true;
    }

    public int hashCode() {
        int result = x;
        result = 31 * result + y;
        return result;
    }
否则,如果您不重写这些方法,
Object
的Javadoc很好地解释了您的问题:

As much as is reasonably practical, the hashCode method defined by
     * class {@code Object} does return distinct integers for distinct
     * objects. (This is typically implemented by converting the internal
     * address of the object into an integer, but this implementation
     * technique is not required by the
     * Java<font size="-2"><sup>TM</sup></font> programming language.)
     *
     * @return  a hash code value for this object.
     * @see     java.lang.Object#equals(java.lang.Object)
     * @see     java.lang.System#identityHashCode
     */
    public native int hashCode();
在合理可行的情况下,由
*类{@code Object}为distinct返回不同的整数
*对象。(这通常通过转换内部
*将对象的地址转换为整数,但此实现
*技术是不需要的
*JavaTM编程语言。)
*
*@返回此对象的哈希代码值。
*@see java.lang.Object#equals(java.lang.Object)
*@see java.lang.System#identityHashCode
*/
公共本机int hashCode();

因此,
新点(1,2)
将不会被视为等于
新点(1,2)
,因此,无法从
映射中检索,因为您使用该点作为hashmap的键,需要覆盖默认的equals和hashCode方法

未测试代码
由于使用点作为hashmap的键,因此需要覆盖默认的equals和hashCode方法

未测试代码
类实现Hashcode/equals?实际上,默认情况下,两个实例被认为是不同的,因为hashcode基于对象的内存地址。啊哈,谢谢!至少它不返回null,但现在它在每行上返回相同的值两次,而不是一个值和一个null。你知道什么地方可能有问题吗?@ThaRemo你测试过你的新equals方法吗?你需要检查它是否为你认为相等的对象返回true,并且它为你认为不同的对象返回false。@ TraceMo你的代码(包括我的HASCODE/EQUALS)很好的输出:<代码>测试:1,1 null null测试:2,2< /代码>什么是错误的?!没关系,我在点构造函数中犯了一个小错误。谢谢!为
类实现Hashcode/equals?实际上,默认情况下,两个实例被认为是不同的,因为hashcode基于对象的内存地址。啊哈,谢谢!至少它不返回null,但现在它在每行上返回相同的值两次,而不是一个值和一个null。你知道什么地方可能有问题吗?@ThaRemo你测试过你的新equals方法吗?你需要检查它是否为你认为相等的对象返回true,并且它为你认为不同的对象返回false。@ TraceMo你的代码(包括我的HASCODE/EQUALS)很好的输出:<代码>测试:1,1 null null测试:2,2< /代码>什么是错误的?!没关系,我在点构造函数中犯了一个小错误。谢谢!扔掉那些“愚蠢的”;)最后返回:替换为:
返回this.x==point.x&&this.y==point.y
删除那些“愚蠢的”;)在末尾返回:替换为:
返回this.x==point.x&&this.y==point.y