Set中的元素為什麼不允許重複

2021-08-17 21:08:10 字數 2496 閱讀 8070

為了弄清楚這個問題 , 我又看了一遍 collection 部分 , 並且看了些其中的原始碼 , 覺得對其中的實現又明白了一點 , 現在說出來和大家共享 .

我們先看一下 set 類的關係圖: 

現在我們就從 set 說起。

set 介面為我們提供了乙個 add() 方法,以讓我們新增元素。所以我們看一下在其實現類 hashset 中是如何實現的呢?

我們看 hashset 中的 add() 方法實現;

public boolean add( e o )

你可能回問怎麼回出來 map 了呢?

map 又是乙個什麼變數呢?

我們來看 map 是在在哪定義的。原來,在 hashset 中定義了這樣的兩個變數:

private transient hashmapmap;

private static final object present = new object();

我們再看一下上面的 add() 方法。

map.put(o, present)==null

實際執行的是 map 的方法,並且我們新增的物件是 map 中的 key,value 是執行的同乙個物件present.

因為map中的key是不允許重複的,所以set中的元素不能重複。

下面我們再看一下, map 又是如何保證其 key 不重複的呢?

現在我們看一下 map 中的 put() 方法的實現:

hashmap 實現了 map ,在 hashmap 中是這樣實現的:

public v put(k key, v value)

}modcount++;

addentry(hash, k, value, i);

return null;

}我們我們按照方法的執行一步一步的來看一下,其實現的過程。

k k = masknull(key);

這一步是要判斷當前的要新增的物件的 key 是否為空,如果為空的話,那麼就生成乙個新的物件作為其 key 。實現如下:

static final object null_key = new object();

* returns internal representation for key. use null_key if key is null.

static t masknull(t key)

之後int hash = hash(k);

我們看一下 hash() 方法的實現:

static int hash(object x)

這一步其實是要得到當前要新增物件的 hashcode, 方法中,首先通過int h = x.hashcode() 取得了當前的要新增物件的 hashcode, 然後

h += ~(h << 9);

h ^=  (h >>> 14);

h +=  (h << 4);

h ^=  (h >>> 10);

生成乙個新的 hashcode.

接著執行的是

(從此處開始,我理解的比較膚淺,請看到此齣的朋友多多指點)

int i = indexfor(hash, table.length);

這個方法是要 returns index for hash code h.

static int indexfor(int h, int length)

下面就要根據 hashmap 中的元素逐個的比較,看是否相同,如果不同就回新增乙個新的元素。是通過迴圈判斷來實現的。

for (entrye = table[i]; e != null; e = e.next)

}通過迴圈判斷是否有完全相同的物件,包括 hashcode 和 value 值。如果已經存在就返回其值,如果不存在就執行一下操作。

modcount++;

addentry(hash, k, value, i);

return null;

物件不存在,首先修改 hashmap 的修改次數,即 modcount 加 1. 然後將物件新增到陣列中。

void addentry(int hash, k key, v value, int bucketindex)

仍然是陣列,我們來看一下 , 在 hashmap 中用來存放物件的陣列的定義:

transient entry table;

至此,我想大家也許應該明白了,為什麼在 set 中是不允許存放重複值的。

通過才的分析,我們可以看到, map 的一些特徵:

1.       在 map 中也是不能存放完全相同的元素的

2.       如果你存入的物件的 key 值已經存在的話,那麼新的 value 將會取代老的 value 值,但是並不會新增新的元素進去。

我們可以通過乙個測試程式來證明這一點:

public void maptest()

執行的結果是:

map   :    

map  size    :   1

map   :    

map  size    :   1

希望此文能大家有所幫助。

HashSet中為什麼不允許放重複的值

主要是因為hahcode hashcode 方法的作用 雜湊演算法,將集合分成若干個區域,每個物件在放入集合之前由計算 機計算出乙個哈吸碼,可以將雜湊碼分組,每組分別對應某個區域,根據乙個物件的雜湊碼可以 確定該物件應儲存在哪個區域。當再次向雜湊表中存入物件的時候,依舊這樣兒運算,但可以快 速的判斷...

為什麼虛構函式不允許丟擲異常

第乙個原因 session session session session 設想如果在析構函式的logdestruction函式中丟擲異常,那麼 endtransaction就不會被呼叫,因為異常發生之後異常點 即logdestruction 之後的語句塊不會被執行。因此會產生資源洩漏。解決方法如下...

Android系統為什麼不允許在子執行緒中訪問UI

這是因為android的ui控制項並不是執行緒安全的,如果多執行緒中併發訪問可能導致ui控制項處於不可預期的狀態.那為什麼系統不對ui控制項的訪問加上鎖機制呢?缺點有兩個 首先,加上鎖機制會讓ui訪問的邏輯變得複雜 其次鎖機制會降低ui訪問的效率,因為鎖機制會阻塞某些執行緒的執行.鑑於這兩個缺點,最...