Java HashMap获取对象的值,该值为;“相等”;但是不同的杂烩?

Java HashMap获取对象的值,该值为;“相等”;但是不同的杂烩?,java,Java,我有一个HashMap数据结构,它包含几个映射到类T的其他实例的点。当我的类实例化如下时,此映射将被赋予一些默认值: T t1 = new T(); T t2 = new T(); Point p1 = new Point(0, 1); Point p2 = new Point(0, 2); HashMap<Point, T> map = new HashMap<Point, T>(); static { map.put(p1, t1); map.put

我有一个
HashMap
数据结构,它包含几个映射到类
T
的其他实例的点。当我的类实例化如下时,此映射将被赋予一些默认值:

T t1 = new T();
T t2 = new T();
Point p1 = new Point(0, 1);
Point p2 = new Point(0, 2);

HashMap<Point, T> map = new HashMap<Point, T>();
static {
    map.put(p1, t1);
    map.put(p2, t2);
}
Point p = new Point(event.getX(), event.getY); // Assume (x, y) = (0, 1) (p1)
if(p.equals(p1)    
    T t = map.get(p);
虽然
p
在这种情况下等于
p1
(x,y)=(0,1),但我从
映射中得到
null
值。我假设这是因为
点(Point2D)中的
hashCode()
方法
使用
equals
以外的内容来计算唯一的哈希值,它应该使用该哈希值来防止冲突

我的问题是:如何使用新实例
p
map
中检索值?是否有另一种数据结构适合该用例

我想我可以使用
toString()
或其他一些映射,比如
HashMap
,或者我可以扩展
类,然后
覆盖
hashCode()
方法来满足我的目的。不过,如果有更干净的方法,这些方法会让我感觉“hacky”(hacky),如果我喜欢听的话。

hashCode()应使用与equals()相同的属性以保持一致

另请参见:

根据

如果根据
equals(Object)
方法,两个对象相等,那么对两个对象中的每一个调用
hashCode
方法必须产生相同的整数结果


在您的案例中,两个
对象似乎相等(根据
等于
方法)但是它们的散列码是不同的。这意味着您需要将
equals
hashCode
函数修正为彼此一致。

您能试着编写一个像下面我们可以运行的那样的自包含示例吗

Map<Point, String> map = new LinkedHashMap<>();
for (int i = 0; i < 10; i++)
    for (int j = 0; j < 10; j++)
        map.put(new Point(i, j), "(" + i + "," + j + ")");

// test the map
int misMatches = 0;
for (int i = 0; i < 10; i++)
    for (int j = 0; j < 10; j++) {
        String expected = "(" + i + "," + j + ")";
        String text = map.get(new Point(i, j));
        if (!expected.equals(text)) {
            System.err.println("Expected <" + expected + "> but got <" + text + ">");
            misMatches++;
        }
    }
System.out.println(misMatches + " mis-matches found.");

我认为Point类的equals()或hashcode()没有任何问题。请尝试以下方法:

public static void main(String args[]) {

        Map<Point, Integer> map = new HashMap<Point, Integer>();
        Point p1 = new Point(0, 1);
        Point p2 = new Point(0, 2);
        map.put(p1,1);
        map.put(p2,2);
        Point p = new Point(0, 1);
        if(p.equals(p1)){
            System.out.println(map.get(p));
        }
        else{
            System.out.println("not");
        }



    }
publicstaticvoidmain(字符串参数[]){
Map Map=newhashmap();
点p1=新点(0,1);
点p2=新点(0,2);
map.put(p1,1);
map.put(p2,2);
点p=新点(0,1);
如果(p等于(p1)){
System.out.println(map.get(p));
}
否则{
系统输出打印项次(“非”);
}
}
它正在产生正确的结果


我猜您没有正确初始化映射。

哈希代码不必是唯一的。冲突是正常的。equals()方法是用来消除歧义的。你有点的实现吗?你能给我们完整的代码或者至少是主要的方法吗?@kabram哈希代码当然需要是唯一的。我想知道是否有另一个数据结构可以满足我的需要?@span:不,哈希代码不需要是唯一的。所以你建议扩展Point或Point2dd重写hashCode()如果我想使用映射?没有其他方法?因为我只使用Java SE类,所以我有点困惑为什么它不工作,只返回null。谢谢,但Point是Java API中的要点,所以如果我要修复它,我需要扩展它。另外,为什么他们会违背自己的建议?Point是Java 1.0;它早于Joshua Bloch“有效的Java“关于如何正确覆盖equals和hashCode的建议将近十年。这就是为什么它与今天的最佳实践不一致的原因。这将解释很多。谢谢!将覆盖我猜:/@span这不是一个建议,而是一个要求。我认为最新JDK版本也覆盖了hash代码(有关如何完成此操作的代码段,请参见).double类型的值的比较可能会有问题。除非您需要
Point
对象与现有Java库绑定,否则您可能会发现最好是滚动您自己的
Point
类,而不是扩展Java的类。非常奇怪,我将对此进行研究。您使用的是ng Java 6或7?我在我的家庭环境中得到了相同的结果,明天我将在其他环境中尝试进一步研究。我使用Java 8,但我不认为它会有任何不同。Point是一个非常古老的类。(超过10年)
public static void main(String args[]) {

        Map<Point, Integer> map = new HashMap<Point, Integer>();
        Point p1 = new Point(0, 1);
        Point p2 = new Point(0, 2);
        map.put(p1,1);
        map.put(p2,2);
        Point p = new Point(0, 1);
        if(p.equals(p1)){
            System.out.println(map.get(p));
        }
        else{
            System.out.println("not");
        }



    }