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