简体   繁体   English

Java-HashMap.containsKey返回对象的错误值

[英]Java - HashMap.containsKey returning incorrect values for Objects

Here is my code: 这是我的代码:

import java.util.HashMap;

class MyString
{
  String string;

  MyString(String string)
  {
    this.string = new String(string);
  }
}

public class test
{

  public void test3()
  {
    HashMap<MyString, Byte> byteHashMap = new HashMap<MyString, Byte>();
    char c = 'A';
    byte b = (byte)c;

    String string = new String("The Letter A");
    MyString myString = new MyString(string);

    byteHashMap.put(myString, b);

    if (byteHashMap.containsKey(myString))
    //if (byteHashMap.containsKey(new MyString(string)))
    {
      System.out.println("true");
    }
    else
    {
      System.out.println("false");
    }
  }

  public static void main(String[] args)
  {
    test testObject = new test();
    testObject.test3();
  }
}

I would like to know why the code, as is, returns true. 我想知道为什么代码按原样返回true。 However, when I switch the if statements (see the commented line), it returns false. 但是,当我切换if语句(请参见注释行)时,它将返回false。

I believe it has something to do with overriding the equals method in the MyString class but I am unsure how to approach this. 我相信这与覆盖MyString类中的equals方法有关,但是我不确定如何处理此问题。

Regards. 问候。

Yes, override hashCode and equals . 是的,重写hashCode equals Right now you will compare a string against the memory reference (standard implementation) of your MyString object. 现在,您将字符串与MyString对象的内存引用(标准实现)进行比较。

example

@Override
public bool equals(Object args0) {
   if(args0 == this) { return true; }
   if(!(args0 instanceof MyString)) { return false; }
   MyString obj = (MyString) args0;

   return obj.getString().equals(this.string); // Create getter
}

@Override
public int hashCode(){
   return this.string.hashCode() * 37;
}

Your belief is correct. 你的信念是正确的。 Map structures rely on .equals to determine if a key already exists in the map or not. 地图结构依靠.equals来确定地图中是否已存在键。 By default, object types have instance equality (meaning a.equals(b) is true if and only if a and b point to the same object). 默认情况下,对象类型具有实例相等性(意味着当且仅当ab指向同一个对象时a.equals(b)为true)。

In your case, you probably want two MyString instances to be equal if the string field is equal. 在您的情况下,如果string字段相等,则可能希望两个MyString实例相等。 In this case, you would override equals with something like: 在这种情况下,您可以使用以下方法覆盖equals

@Override
public boolean equals(Object other) {
    if (other == null) { return false; }
    if (!(other instanceof MyString)) { return false; }
    MyString m = (MyString)other;
    return this.string.equals(m.string);
}

With this, either of the two if statements would return true. 这样,两个if语句中的任何一个将返回true。

You should also override hashCode . 您还应该重写hashCode If you use Eclipse, it can generate these two methods for you quite easily via the Source menu. 如果使用Eclipse,它可以通过“ Source菜单很容易地为您生成这两种方法。

You need to implement hashCode and equals. 您需要实现hashCode和equals。 HashMaps put objects in buckets based on the hashCode. HashMaps根据hashCode将对象放入存储桶中。 Different objects can have the same hashCode, but the rule is that two equal objects must have the same hashCode. 不同的对象可以具有相同的hashCode,但是规则是两个相等的对象必须具有相同的hashCode。 Once the HashMap finds all of the entries with the same hashCode, it then checks for equality using the equals method. 一旦HashMap找到具有相同hashCode的所有条目,便使用equals方法检查是否相等。

The default implementation checks for object instance equality - that is, are the two objects the same instance. 默认实现检查对象实例是否相等-也就是说,两个对象是同一实例。 In your case, you're checking two different instances. 就您而言,您要检查两个不同的实例。

Override the equals and hashCode methods to pass through the values returned by hashCode() and equals() for the private String member variable, assuming that's all that determines if two instances of your class are equal. 假设所有决定类的两个实例是否相等的方法,都重写equals和hashCode方法以传递hashCode()和equals()返回的私有String成员变量的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM