我有點難以理解java-9的實現細節ImmutableCollections.SetN
;特別是爲什麼需要增加兩次內部數組。ImmutableCollections SetN實現細節
假如你這樣做:
Set.of(1,2,3,4) // 4 elements, but internal array is 8
更確切地說我完全理解爲什麼這是在HashMap
的情況下完成的(雙膨脹) - 在這裏你永遠(幾乎)希望load_factor
是一個。例如,值爲!=1
可以改善搜索時間,因爲條目可以更好地分散到存儲區中。
但在不可變的情況下設置 - 我真的不知道。特別是因爲內部數組的索引被選中。
讓我提供一些細節。首先如何搜索索引:
int idx = Math.floorMod(pe.hashCode()^SALT, elements.length);
pe
是我們在集合中的實際值。 SALT
只是在啓動時產生的32位,每JVM
一次(如果您需要,這是實際的隨機化)。我們的例子中的elements.length
是8
(4個元素,但這裏是8個 - 大小的兩倍)。
該表達式類似於負安全模運算。請注意,在選擇存儲桶時,在HashMap
中例如((n - 1) & hash
)完成了相同的邏輯。
因此,如果我們的情況爲elements.length is 8
,那麼此表達式將返回小於8的任何正數值。(0, 1, 2, 3, 4, 5, 6, 7)
。
現在該方法的其餘部分:
while (true) {
E ee = elements[idx];
if (ee == null) {
return -idx - 1;
} else if (pe.equals(ee)) {
return idx;
} else if (++idx == elements.length) {
idx = 0;
}
}
讓我們來分析一下:
if (ee == null) {
return -idx - 1;
這是好事,這意味着數組中的當前插槽是空的 - 我們可以把我們的價值在那裏。
} else if (pe.equals(ee)) {
return idx;
這是壞的 - 插槽被佔用,已經存在的條目等於我們想要放置的條目。 Set
s不能有重複的元素 - 所以後面拋出一個異常。
else if (++idx == elements.length) {
idx = 0;
}
這意味着這個槽被佔用(散列衝突),但是元素不相等。在HashMap
這個條目將被放在與LinkedNode
或TreeNode
相同的桶 - 但在這裏並不是這樣。
因此index
增加,並嘗試下一個位置(小的警告,它在它到達最後位置時以循環方式移動)。
這裏有一個問題:如果在搜索索引時沒有什麼太花哨的東西(除非我錯過了某些東西),爲什麼需要將數組放大兩倍?爲什麼功能不這樣寫的:
int idx = Math.floorMod(pe.hashCode()^SALT, input.length);
// notice the diff elements.length (8) and not input.length (4)
@GhostCat https://github.com/netroby/jdk9-dev/blob/master/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java#L446-L547('probe '方法) –
@VinceEmigh要完成其他討論:通常事情不是黑色或白色。我看到很多6digits的人提供的答案確實提供了更少的內容或更多的「fuziness」,但在幾個小時內獲得了大量的選票。我看到好的內容坐了很長時間......並沒有發生任何事情。你會看到 - 零其他答案,甚至沒有評論這個問題。所以也許一個可能的解釋清單並不能解釋一個很好的答案 - 但它可以提供思考的食物。除此之外:這不是什麼投票的目的?我會以直接反饋的形式記錄下來...以及:我嘗試做 – GhostCat
@VinceEmigh在下一次提出更好的建議。 – GhostCat