HashSet與HashMap比較——新增物件已存在處理方式一樣?

dreamcasher發表於2018-08-06

答案是不一樣的。

HashSet與HasMap在新增新物件是,會先判斷容器中是否已存在相等的物件(比較key是否相等),如果存在,HashSet的處理方式是放棄儲存新物件,然而HashMap的處理方式是覆蓋之前的物件。

相等物件:如果兩個引用指向同一個物件,那麼這兩個引用是相等的,他們的hashcode方法返回的值一致。如果沒有重寫Object中hashcode方法,返回的是物件在記憶體中的地址(值中帶有‘@’)。所以必須要要重寫hashCode()方法,才能使得兩個物件都有相同的hashCode,並且還要重寫equals()方法使得返回的值為true。滿足這兩個條件,那麼證明兩個物件在HashMap/HashSet中是相等的。

用一段測試程式碼來展示:

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


import lombok.Data;

public class TestHashSetAndHashMap {
  @Data
  public static class Person {
    private Integer id;
    private String name;

    public Person(Integer id, String name) {
      this.id = id;
      this.name = name;
    }

    public Person(){}

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      Person person = (Person) o;
      return Objects.equals(id, person.id);
    }

    @Override
    public int hashCode() {

      return Objects.hash(id);
    }
  }
  public static void main(String[] args) {
    Person p1 = new Person(1,"zhangshan");
    Person p2 = new Person(1, "Lisi");
    Set<Person> set = new HashSet<>();
    set.add(p1);
    for (Person p : set) {
      System.out.println(p.getName());
    }
    set.add(p2);
    for (Person p : set) {
      System.out.println(p.getName());
    }
    //HashMap是覆蓋
    Map<Integer, Person> map = new HashMap<>();
    map.put(p1.getId(), p1);
    for (Map.Entry e : map.entrySet()) {
      System.out.println(e.getValue());
    }
    map.put(p2.getId(), p2);
    for (Map.Entry e : map.entrySet()) {
      System.out.println(e.getValue());
    }
  }
}

結果:

32
32
zhangshan
zhangshan
TestHashSetAndHashMap.Person(id=1, name=zhangshan)
TestHashSetAndHashMap.Person(id=1, name=Lisi)

可以看出HashSet放棄儲存新物件,HashMap直接覆蓋原有物件。

相關文章