12

2番目と3番目のセットが順序を保持するのはなぜですか。

Integer[] j = new Integer[]{3,4,5,6,7,8,9};
LinkedHashSet<Integer> i = new LinkedHashSet<Integer>();
Collections.addAll(i,j);
System.out.println(i); 

HashSet<Integer> hi = new HashSet<Integer>(i);
System.out.println(hi); 

LinkedHashSet<Integer> o = new LinkedHashSet<Integer>(hi);
System.out.println(o); 

これが私が得る出力です:

3,4,5,6,7,8,9
3,4,5,6,7,8,9
3,4,5,6,7,8,9
4

2 に答える 2

17

2番目のもの(を使用するだけHashSet)は単なる偶然です。JavaDocsから:

このクラスは、ハッシュテーブル(実際にはHashMapインスタンス)に裏打ちされたSetインターフェイスを実装します。セットの反復順序については保証されません。特に、順序が時間の経過とともに一定に保たれることを保証するものではありません。このクラスはnull要素を許可します。

3番目(LinkedHashSet)は次のように設計されています。

予測可能な反復順序を使用した、Setインターフェイスのハッシュテーブルとリンクリストの実装。この実装は、すべてのエントリを介して実行される二重リンクリストを維持するという点でHashSetとは異なります。このリンクリストは、要素がセットに挿入された順序(挿入順序)である反復順序を定義します。要素がセットに再挿入されても、挿入順序は影響を受けないことに注意してください。(s.contains(e)が呼び出しの直前にtrueを返すときに、s.add(e)が呼び出された場合、要素eはセットsに再挿入されます。)

于 2012-02-19T00:55:38.380 に答える
5

@Behrangの答えは良いですが、より具体的には、HashSetがと同じ順序であるように見える唯一の理由LinkedHashSetinteger.hashCode()、整数値自体であるため、HashSet内部ストレージで数値が順番になっているためです。これは非常に実装固有であり、@ Behrangが言うように、実際には偶然です。

たとえば、new HashSet<>(4)バケットの初期数を(16ではなく)4に設定するを使用すると、次の出力が得られる可能性があります。

HashSet<Integer> hi = new HashSet<Integer>(4);
...
[3, 4, 5, 6, 7, 8, 9]
[8, 9, 3, 4, 5, 6, 7]
[8, 9, 3, 4, 5, 6, 7]

16以上の値でスタックしている場合は、次のようになる可能性があります。

Integer[] j = new Integer[] { 3, 4, 5, 6, 7, 8, 9, 16 };
...
[3, 4, 5, 6, 7, 8, 9, 16]
[16, 3, 4, 5, 6, 7, 8, 9]
[16, 3, 4, 5, 6, 7, 8, 9]
于 2016-01-26T00:08:24.797 に答える