簡體   English   中英

為什么我的程序的 HashSet 順序總是相同的?

[英]Why HashSet order always same for my program?

對於一些教程,他們說:

HashSet 不保持任何順序,元素將以任何隨機順序返回。

但是我寫了一個測試程序,結果總是一樣。

import java.util.*;

public class HashSetDemo {

    public static void main(String[] args) {
        HashSet<String> hs1 = new HashSet<String>();
        hs1.add("a");
        hs1.add("b");
        hs1.add("c");
        hs1.add("d");
        hs1.add(null);
        hs1.add(null);
        System.out.println(hs1);
        System.out.println(hs1);
    }
}

輸出:

[null, a, b, c, d]
[null, a, b, c, d]

我試了很多次,但順序總是一樣的。 為什么? 希望有人可以幫助我,在此先感謝!

這種行為的原因是HashSetHashMap支持,而HashMap又由Entry對象array支持。 其中hash用於查找arrayindex 所以在HashSet總是有一個元素的順序( array的順序),你只是不能保證這個順序是什么。

據我所知, HashSet的順序由其元素的計算hashes的順序決定(或至少影響)。 然后,對於相對簡單的輸入(例如您的單個字符串),人們可能會假設hashes有嚴格的排序,這會給您看起來是自然的排序。 對於更復雜的對象,因此更復雜的hash計算, hashes將更加分散,並且排序“更加隨機”。

此外,就像有人指出的那樣,“不保證排序”並不意味着“保證隨機排序”。

String類的hashcode方法也在這里發揮作用,對於單個字符String s, hashcode將只是String一個charint值。 並且由於charint值按字母順序排列,因此單個char String的計算hashes值也是如此。

僅僅因為他們不能保證維持秩序並不意味着他們有時不會處於秩序狀態。

如果您需要排序,請使用不同的集合 - 例如樹集。

正如我們看到的文件

它不保證集合的迭代順序; 特別是,它不保證訂單會隨着時間的推移保持不變。

它確實保持但不保證。 添加后隨着時間的推移,刪除幾次您可以看到差異。

當然不是隨機順序,對於某個輸入,迭代器的順序是固定的,我想他們想說的順序可能與輸入順序不同。 事實上,這里的順序取決於String.hashCode()String.equals()set.add()調用的順序。

當您調用System.out.print(set) ,您的意思是System.out.print(set.toString()) ,而set.toString()調用 set 的迭代器來訪問所有元素。

HashSet 不保證它,但它並不意味着它必須更改順序。 如果沒有添加任何內容,則無需更改順序。 例如看看這個例子

hs1.add("c");
hs1.add("b");
hs1.add("d");
hs1.add("g");
hs1.add(null);
hs1.add(null);
System.out.println(hs1);

輸出: [null, b, c, d, g]

然后我們添加一個新元素並再次打印:

    hs1.add("a");
    System.out.println(hs1);

輸出: [null, a, b, c, d, g]

如您所見,它在某種程度上改變了順序。

沒有什么是保證的,但這並不意味着它必須不遺余力地更改訂單

HashSet順序不是隨機的,它依賴於實現,並且實現可以自由更改。 JDK 8 中進行了顯着更改。因此,如果您升級到 Java 8,您可能會看到HashMap順序發生了變化。 如果您使用像 IBM 這樣的非 Oracle JDK,它也可能會有所不同。 一般來說,你永遠不應該依賴它,否則你的程序將來可能會崩潰。

HashSet() 沒有任何順序。 它也不支持輸入順序。 但順序不是隨機的。 即使您更改版本並升級,該版本的輸出也會更改並保持不變。 通過實現您的源代碼,我得到了一些不同的答案,如下所示。 我已連續多次執行此代碼,但輸出相同。

[a, b, c, d, 空]

還有一件事,HashSet() 不支持重復,因此,添加重復的“null”只會增加代碼的長度。

HashSet使用二進制搜索來查找可能的重復項,並且必須在它們的散列 ( hashCode() ) 之后對列表中的對象進行排序才能這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM