【问题标题】:hash code HashMap [duplicate]哈希码HashMap [重复]
【发布时间】:2013-08-28 10:02:27
【问题描述】:

我正在努力学习 Java。 Eric Roberts 的文本“Java 的艺术与科学”有一个编程任务,我们在其中模拟航班预订控制台。我想通过使用只有城市字符串的城市类来“分类”。它只有一个字段name,它是一个字符串,但我正在尝试学习如何使用类。

无论如何,所以我不得不重写 City 类中的 equals 方法以避免重复。所以我不得不重写 hashCode 方法。

现在我的HashMap<City,ArrayList<Flight>> 不工作了。它找不到某些值,但仍然允许重复键。

我的城市equalshashCode 覆盖如下。谁能看到为什么我的 HashMap 出错了?

/* (non-Javadoc)
 * @see java.lang.Object#equals(java.lang.Object)
 */
@Override
public boolean equals(Object that) {
    // TODO Auto-generated method stub
    if ( this == that ) return true;
    if ( !( that instanceof City) ) return false;
    City aThat = (City) that;
    return (name == aThat.name );
}

@Override
public int hashCode() {
    // TODO Auto-generated method stub
    return name.hashCode();
}

【问题讨论】:

  • 问题在于如何比较字符串变量:“name == aThat.name”。通过使用“==”,您只是在比较对象引用而不是内容,与“this == that”相同。要比较 String 对象的内容,您需要 String 对象的 euquals* 方法。与 C++ 不同,您可以在代码中使用的每个对象都只是该对象的引用,Java 中也没有运算符重载。

标签: java hashmap equals hashcode


【解决方案1】:

对于对象比较使用 equals() 而不是 == ,因为 == 比较引用值以确定它们是否指向同一个对象。

@Override
public boolean equals(Object that) {
    //more code
    return (name.equals(aThat.name) );
}

顺便说一句,您的hashCode() 也很糟糕,因为您的name 可能为空,您将获得NullPointerException

@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

最后的建议是,我不建议您像您的 hashMap mutable objects 那样在 hash structure 中用作键,因为它的 hashCode() 会发生变化,并且可能会发生意外行为。最好使用inmutable objects 作为键。如果 City 类是不可变的,则可以,但如果不是,则更改它。

【讨论】:

  • == 比较参考值以确定它们是否指向同一个对象。 -1 表示草率。
  • @EJP 对不起,你没看错!我的英语不好
【解决方案2】:

当检查对象的值是否相同时,不要使用 ==。而是使用 .equals,在您的 equals 方法中将 == 更改为 .equals,

例如

String str1 = "Foo bar";
String str2 = "Foo bar";
str1 == str2 // not always true!
str1.equals(str2) // very true

@Override
public boolean equals(Object that) {
    // TODO Auto-generated method stub
    if ( this == that ) return true;
    if ( !( that instanceof City) ) return false;
    City aThat = (City) that;
    return (name.equals(aThat.name) );   // <--- see edit 
}

【讨论】:

  • -1 用于错误地描述 == 的用法,并从 OP 的源代码中删除了实际正确的行。 == 在比较对象引用时有效,并且 OP 代码中的行恰好是有效的情况。通常当我们实现equals()时,首先要检查的是传入的obj ref是否与this引用相同的对象,如果是,则它们是相等的,我们可以跳过所有后续的繁重检查。
  • 好吧,我不想详细介绍 == 的工作原理,因为他显然是 java 的新手,我相信如果他们愿意,他/她有能力进一步研究它。而且我不相信 String 对象上的 .equals 应该被视为繁重的检查。
  • 正如我所说: 1. 'should never use ==' 这句话是完全不正确的,没什么好争论的。 2. 用这个检查输入 obj ref 只是实现equals() 的非常正常的做法,要求 OP 删除该行简直是误导。我认为有更好的方法来简化答案,而不是给出错误的陈述。
  • 删除 this == that 优化是个坏主意(根据经验)
  • 你的str1 == str2 // not always true! 是,嗯,不是真的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-21
  • 2013-06-20
  • 2016-03-18
  • 2014-05-21
  • 2012-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多