Java HashMap containsKey

Tec*_*ast 6 java hashmap containskey

我有以下代码

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class Person {
  private String name;
  private long birthTime;

  @Override
  public int hashCode() {
    return Objects.hash(name, birthTime);
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!(obj instanceof Person)) {
      return false;
    }
    Person other = (Person) obj;
    return Objects.equals(name, other.name)
        && birthTime == other.birthTime;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public long getBirthTime() {
    return birthTime;
  }

  public void setBirthTime(long birthTime) {
    this.birthTime = birthTime;
  }

  public static Person person(String name, long time) {
    Person p = new Person();
    p.setName(name);
    p.setBirthTime(time);
    return p;
  }

  public static void main(String[] args) {
    Map<Person, Person> map = new HashMap<>();
    Person p = person("alice", 3);
    System.out.println("1. " + map.containsKey(p));

    map.put(p, p);
    System.out.println("2. " + map.containsKey(p));

    p.setName("charlie");
    System.out.println("3. " + map.containsKey(p));

    Person p2 = person("alice", 3);
    System.out.println("4. " + map.containsKey(p2));

    Person p3 = person("charlie", 3);
    System.out.println("5. " + map.containsKey(p3));
  }
}
Run Code Online (Sandbox Code Playgroud)

我期望输出为假、真、真、假和真。但是,输出是假,真,假,假,假。

我正在寻找第 3 种和第 5 种情况的输出如何为假。HashMap containsKey 的行为是什么?

即使 Key 对象在 Map 中,为什么输出仍为 false。对于 Person 类,equals 和 hashcode 方法都被覆盖。

Era*_*ran 6

以下语句破坏了您的地图:

p.setName("charlie");
Run Code Online (Sandbox Code Playgroud)

它导致变量引用的键p不再位于与其匹配的 bin 中hashCode(),因为您正在更改它的hashCode().

如果更改影响hashCode()或的结果,则永远不应更改已在 Map 中的键的状态equals()

p.setName("charlie");
System.out.println("3. " + map.containsKey(p));
Run Code Online (Sandbox Code Playgroud)

返回,false因为Person名称为“charlie”的Person实例与名称为“alice”的实例未映射到相同的 bin 。因此在与名称“charlie”匹配的 bin 中containsKey()搜索,但p在那里找不到它。

Person p2 = person("alice", 3);
System.out.println("4. " + map.containsKey(p2));
Run Code Online (Sandbox Code Playgroud)

返回false因为p2不等于p(它们具有不同的名称)。

Person p3 = person("charlie", 3);
System.out.println("5. " + map.containsKey(p3));
Run Code Online (Sandbox Code Playgroud)

返回,false因为密钥p位于与名称“alice”匹配的 bin 中,即使其当前名称是“charlie”,因此containsKey()在错误的 bin 中搜索它,但没有找到它。