天天看點

Java Set集合通過重寫hashCode和equals實作去重

  • 需求:在嵌套擷取分類節點子節點的時候,需要對擷取的位元組點進行去重,是以采用了Set集合,也就是沒有重複資料的特性
  • 具體解決思路

    在Set中如果存儲類型是基本類型,也就是系統已經封裝好的類型,那麼就不需要重寫hashCode和equals這兩個方法,但是如果是我們自己定義的Bean類型,就需要對如何判斷重複進行自定義。

  • ​​Set去重流程​​

我在裡面看到了很重要的一點:先判斷hashCode是否相同再判斷equals是否相同

for (Entry<K,V> e = table[i]; e != null; e = e.next) {//每添加一個,則循環判斷是否與map中的元素相等
            Object k;
            // 先判斷hashcode是否一緻,然後再判斷值是否相等
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }      
  • 複雜對象解決思路
(先執行hashCode方法),則會去執行equals方法,比較每個屬性的值
 * 如果一緻的話,則不會存進set,否則加入set集合 
 * 
public class MmallCategory implements Serializable {
    private Integer id;
    private Integer parentId;
    private static final long serialVersionUID = 1L;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MmallCategory category = (MmallCategory) o;
        //隻是比較id,隻有屬性值一緻才會傳回true
        return id != null ? id.equals(category.id) : category.id == null;
    }

    /**
     * 重寫hashCode方法,傳回的hashCode不一樣才會再去比較每一個屬性的值
     * @return
     */
    @Override
    public int hashCode() {
        //return id.hashCode
        return id != null ? id.hashCode() : 0;
    }      

總結:根據實作類和Set流程的關鍵代碼我就明白了。

根據Set流程部落格的連結,HashSet的add方法其實依賴于HashMap的put方法

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
    }      
public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
            //擷取hashCode
        int hash = hash(key.hashCode());
        //這個應該似乎是找出對應index索引
        int i = indexFor(hash, table.length);
        //每添加一個,則循環判斷是否與map中的元素相等
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            // 先判斷hashcode是否一緻,然後再判斷值是否相等
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
    //周遊完不重複
        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }