HashSetとLinkedHashSet


153

それらの違いは何ですか?そんなこと知ってる

LinkedHashSetは、すべての要素にわたって二重にリンクされたリストを維持する、HashSetの順序付きバージョンです。反復順序を気にする場合は、HashSetの代わりにこのクラスを使用してください。HashSetを反復処理する場合、順序は予測できませんが、LinkedHashSetを使用すると、要素が挿入された順序で要素を反復処理できます。

しかし、LinkedHashSetのソースコードには、HashSetの呼び出しコンストラクターしかありません。では、二重リンクリストと挿入順序はどこにあるのでしょうか。


2
Intellij(Ctrl + B)オプションを使用して、回答を追跡します。:)
Delta

もちろん、ソースコードを添付する必要があります。:)
デルタ

回答:


65

答えは、基本クラスを構築するためにが使用するコンストラクターにありLinkedHashSetます。

public LinkedHashSet(int initialCapacity, float loadFactor) {
    super(initialCapacity, loadFactor, true);      // <-- boolean dummy argument
}

...

public LinkedHashSet(int initialCapacity) {
    super(initialCapacity, .75f, true);            // <-- boolean dummy argument
}

...

public LinkedHashSet() {
    super(16, .75f, true);                         // <-- boolean dummy argument
}

...

public LinkedHashSet(Collection<? extends E> c) {
    super(Math.max(2*c.size(), 11), .75f, true);   // <-- boolean dummy argument
    addAll(c);
}

そして、(一例)HashSetブール引数を取るコンストラクタが記述されており、このようになります:

/**
 * Constructs a new, empty linked hash set.  (This package private
 * constructor is only used by LinkedHashSet.) The backing
 * HashMap instance is a LinkedHashMap with the specified initial
 * capacity and the specified load factor.
 *
 * @param      initialCapacity   the initial capacity of the hash map
 * @param      loadFactor        the load factor of the hash map
 * @param      dummy             ignored (distinguishes this
 *             constructor from other int, float constructor.)
 * @throws     IllegalArgumentException if the initial capacity is less
 *             than zero, or if the load factor is nonpositive
 */
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);
}

2
子クラスに対して明示的に機能を備えた親クラス、区別するために無視された引数
Traubenfuchs

5
コンストラクタの曖昧性解消のためにダミーパラメータを使用している、正確な設計ではありません。
エリックJ.

8
APIはクリーンであるため、かなりクリーンな設計です(このHashSetコンストラクターはパッケージプライベートです)。実装の詳細は、クラスのユーザーにとって重要ではありません。このコードを維持することはより困難になる可能性がありますが、java.utilクラスの場合、非常に小さなパフォーマンス改善でもそれを正当化できます。
lbalazscs

25

LinkedHashSetのコンストラクターは、次の基本クラスコンストラクターを呼び出します。

HashSet(int initialCapacity, float loadFactor, boolean dummy) {
  map = new LinkedHashMap<E, Object>(initialCapacity, loadFactor);
}

ご覧のとおり、内部マップはLinkedHashMapです。内部を見るとLinkedHashMap、次のフィールドが見つかります。

private transient Entry<K, V> header;

これは問題のリンクされたリストです。


24

HashSet順不同ソートされていないセットです。
LinkedHashSetは、HashSet の注文バージョンです。

唯一の違いHashSetのLinkedHashSetのは:ということです
LinkedHashSetのは、挿入順序を保持します。

HashSetを反復処理する場合、順序は予測できませんが、LinkedHashSetの場合は予測可能です

LinkedHashSetが挿入順序を維持する理由は、次のとおりです
。使用されている基本的なデータ構造はDoubly-Linked-Listです。


9

あなたはのソースを見てみなければならないHashSet、それは裏を作る特殊なコンストラクタです...それが呼び出すコンストラクタだけではなく。MapLinkedHashMapHashMap


おかげで、HashSetには、LinkedHashSetで呼び出されるLinkedHashMapを作成するためのコンストラクターがあり、すべてのロジックはLinkedHashMapにあります
Shikarn-O

5

全体的にパフォーマンスLinkedHashSet向上するため、ほとんどの場合は使用することをお勧めします):

  1. 予測可能な 反復順序LinkedHashSet(Oracle)
  2. LinkedHashSetは、HashSetよりも挿入にコストがかかります。
  3. HashMapほとんどの場合、反復処理にSet構造体を使用するため、一般的には、パフォーマンスが若干向上します。

パフォーマンステスト:

------------- TreeSet -------------
 size       add  contains   iterate
   10       746       173        89
  100       501       264        68
 1000       714       410        69
10000      1975       552        69
------------- HashSet -------------
 size       add  contains   iterate
   10       308        91        94
  100       178        75        73
 1000       216       110        72
10000       711       215       100
---------- LinkedHashSet ----------
 size       add  contains   iterate
   10       350        65        83
  100       270        74        55
 1000       303       111        54
10000      1615       256        58

ソーステストページはこちらからご覧いただけます:最終的なパフォーマンステストの例


2
これらの「ベンチマーク」の前にJVMがウォームアップすることはないので、そのデータを真剣に受け止めません。続きを読む
Felix S

3

HashSet:実際には順序付けされていません。パラメータを渡す場合は

Set<Integer> set=new HashSet<Integer>();
for(int i=0;i<set.length;i++)
{
  SOP(set)`enter code here`
}

出力:2,1,3予測できない場合があります。次回別の注文。

LinkedHashSet() FIFOオーダーを生成します。


3

HashSet 挿入アイテムの順序を維持しない挿入アイテムの順序を
LinkedHashSet 維持する

Set<String> set = ...;// using new HashSet<>() OR new LinkedHashSet<>()
set.add("2");
set.add("1");
set.add("ab");
for(String value : set){
   System.out.println(value);
}  

HashSet 出力

1
ab
2

LinkedHashSet 出力

2
1
ab

2

HashSet:

下線が引かれたデータ構造はHashtableです。重複するオブジェクトは許可されません。挿入順序は保持されず、オブジェクトのハッシュコードに基づいています。null挿入が可能です(1回のみ)。Serializable、Clonableを実装していますが、RandomAccessインターフェースは実装していません。HashSetは、頻繁な操作が検索操作である場合に最適です。

HashSetでは、複製は許可されていません。コンパイル例外またはランタイム例外が発生しないときにユーザーが複製を挿入しようとした場合。addメソッドは単にfalseを返します。

コンストラクタ:

HashSet h = new HashSet(); 空のHashSetオブジェクトをデフォルトの初期容量16で作成し、デフォルトの充填率(負荷係数)は0.75です。

HashSet h = new HashSet(int initialCapacity); 指定されたinitialCapacityで空のHashSetオブジェクトを作成し、デフォルトの塗りつぶし比率は0.75です。

HashSet h = new HashSet(int initialCapacity、float fillRatio);

HashSet h = new HashSet(Collection c); 指定されたコレクションに対応するHashSetオブジェクトを作成します。このコンストラクタは、コレクションオブジェクト間の相互変換を目的としています。

LinkedHashSet:

HashSetの子クラスです。次の違いを除いて、(コンストラクタとメソッド)を含むHashSetとまったく同じです。

相違点HashSet:

  1. 下線が引かれたデータ構造はHashtableです。
  2. 広告掲載の順序は保持されません。
  3. 1.2バージョンを導入。

LinkedHashSet:

  1. 下線が引かれたデータ構造は、LinkedListとHashtableの組み合わせです。
  2. 挿入順序は保持されます。
  3. 1.4バージョンで導入されました。

1

LinkedHashSetクラスから呼び出されたコンストラクターを見ると、内部的にLinkedHashMapはバッキングの目的で使用されていることがわかります。


0

すべてのメソッドとコンストラクターは同じですが、LinkedHashsetは挿入順序を維持しますが重複は許可しない点が唯一の違いです。

ハッシュセットは挿入順序を維持しません。シンプルなリストとセットの組み合わせです:)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.