- 需求:在嵌套擷取分類節點子節點的時候,需要對擷取的位元組點進行去重,是以采用了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;
}