關于java裡面的集合,大家經常利用到Set集合沒有重複資料的特性,來進行資料的去重,那麼去重的原理是怎麼樣的呢?
最近面試了幾個人,其間有聊到集合的東西,是以就順便問了一下這個問題,但是都是隻知道這麼用,
而沒有去看看底層代碼的去重原理(而恰恰有可能這些基礎原理會被用來設計其他一些場景實作),
是以在此文章記錄一下,希望能幫助到一些人:
下面是Set集合的類圖:

下面我們來跟蹤一下執行的過程:
1. 首先我們執行個體化一個set對象
Set<8大基本類型> set = new HashSet<8大基本類型>();
set.add(8大基本類型);
2.add操作會調用HashSet中的add方法,實作如下:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
3.HashSet中的add方法依賴了HashMap的put方法,實作如下:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
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;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
很明顯上述操作對8種基本類型的資料+String型是有用的,但是如果想把去重的方式應用到複雜的對象呢,上述方式就還欠缺了一點了,
知道了執行順序和原理了的話,就知道該如何去實作了!
下面就是重寫對象User的實作,重寫equals和hashCode方法!
測試類:
package com.test.set;
import java.util.HashSet;
import java.util.Set;
public class UniqueSet {
/**
*
* @param args
*/
public static void main(String[] args) {
User user1 = new User(1, "a");
User user2 = new User(2, "b");
User user3 = new User(3, "c");
User user4 = new User(2, "b");
Set<User> userSet = new HashSet<User>();
userSet.add(user1);
userSet.add(user2);
userSet.add(user3);
userSet.add(user4);
// 輸入結果 id=1 username=a id=2 username=b id=3 username=c
for (User u : userSet) {
System.out.println("id=" + u.id + " " + "username=" + u.username);
}
}
}
實作類:
package com.test.set;
/**
* 類描述:set集合針對String 類型和8大基礎資料類型 過濾掉重複資料,
* 如果存放的是其他類型對象,則需要重寫hashCode方法和equals方法,
* 當hashcode相等時(先執行hashCode方法),則會去執行equals方法,比較每個屬性的值
* 如果一緻的話,則不會存進set,否則加入set集合
*
*/
public class User {
// id
protected Integer id;
// 名稱
protected String username;
//構造方法
public User(Integer id, String username) {
this.id = id;
this.username = username;
}
/**
* 如果對象類型是User,先比較hashcode,一緻的場合再比較每個屬性的值
*/
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (this == obj)
return true;
if (obj instanceof User) {
User user = (User) obj;
// if(user.id = this.id) return true; // 隻比較id
// 比較每個屬性的值 一緻時才傳回true
if (user.id == this.id && user.username.equals(this.username))
return true;
}
return false;
}
/**
* 重寫hashcode 方法,傳回的hashCode不一樣才再去比較每個屬性的值
*/
@Override
public int hashCode() {
// return id.hashCode();
return id.hashCode() * username.hashCode();
}
}
以上---------------------