Javaセットは注文を保持しますか?


179

Javaセットは順序を保持しますか?メソッドがSetを私に返し、データは順序付けされていると考えられますが、Setを反復処理すると、データは順序付けられません。これを管理するより良い方法はありますか?Set以外のものを返すようにメソッドを変更する必要がありますか?


3
「要素は特定の順序で返されません(このセットが保証を提供するいくつかのクラスのインスタンスでない限り)。」セットのイテレータメソッドが言うことです。見つかっここに
カイザー

回答:


256

Setインタフェースは、任意の順序保証を提供していません。

そのサブインターフェースSortedSetは、いくつかの基準に従ってソートされたセットを表します。Java 6には、を実装する2つの標準コンテナーがありますSortedSet。彼らは、あるTreeSetConcurrentSkipListSet

SortedSetインターフェースに加えて、LinkedHashSetクラスもあります。要素がセットに挿入された順序を記憶し、その要素をその順序で返します。


21
さらに、Java 8では文字列ハッシュ異なるため、セットとマップのデフォルトの(ソートされていない)順序が変更されます。あなたがソートされていない順序に依存している場合は、あなたのコードは、Java 8の下で異なる動作をします
rustyx

私はクラスの順序付けが正常ではないことを理解していますが、期待されていた動作はそれらが導入されたままにしておくことであり、順序を乱すのではなく、要素が集約されるたびに要素をシャッフルするだけです。あなたのソリューションは最適化されていません。それは、ソートするために構造全体を実装する必要があるためです。導入されたのと
同じ方法

@White_King:セットは、「挿入順序」の概念を含まない数学的な概念なので、Javaインターフェースがその規則に従うのは理にかなっています。順序付けられたセットがありますが、順序は関係(Javaのコンパレータ)によって指定され、セット理論の定義をJavaの定義と一致させます。挿入順序を維持するというあなたの期待はおそらくリストから来るでしょうが、セットはリストではありません。
KonradHöffner19年

103

LinkedHashSetが必要です。


43
A ListSet(メンバーシップの一意性を保証するものではありません)ではありません。
限定的な贖罪

10
多くのビジネス特有のケースでは、リストをセットの代わりに保持するためだけにリストを使用することはできません。LinkedHashSetは順序を維持し、一意に保存します。
gubs

18

メンバーの多くが提案したように、LinkedHashSetを使用してコレクションの順序を保持します。Uはこの実装を使用してセットをラップできます。

SortedSetの実装は、ソート順に使用できますが、目的にはLinkedHashSetを使用してください

また、ドキュメントから、

「この実装は、TreeSetに関連するコストの増加を招くことなく、HashSetによって提供される不特定の、一般的に無秩序な順序付けからクライアントを保護します。元の形式に関係なく、元の形式と同じ順序を持つセットのコピーを作成するために使用できます。セットの実装:」

ソース:http : //docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html


9

セットは単なるインターフェースです。順序を維持するには、そのインターフェースとサブインターフェースSortedSetの特定の実装、たとえばTreeSetやLinkedHashSetを使用する必要があります。このようにしてSetをラップできます:

Set myOrderedSet = new LinkedHashSet(mySet);

7

以下は、SetJavaで利用可能な標準実装の順序特性の概要です。

  1. 挿入順序を維持する:LinkedHashSetおよびCopyOnWriteArraySet(スレッドセーフ)
  2. セット内で項目をソートしたままにします:TreeSetEnumSet(列挙型に固有)およびConcurrentSkipListSet(スレッドセーフ)
  3. アイテムを特定の順序で保持しません:HashSet(試行したもの)

特定のケースでは、最初にアイテムを並べ替えてから、1または2のいずれかを使用できます(最も可能性が高いLinkedHashSetまたはTreeSet)。または、別の方法でより効率的に、自動的にソートを処理するにソートされていないデータを追加することもできTreeSetます。


7

注文を保持するには、Listまたはを使用しLinkedHashSetます。


1
それはだLinkedHashSet、ではありません... Map
Marko Topolnik、2012年

リストではなくセットが必要ですが、私が推測するオブジェクトの注入順序も保持するセットが必要です
White_King

5

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


3

のjavadocからSet.iterator()

このセットの要素の反復子を返します。要素は特定の順序で返されません(このセットが保証を提供するいくつかのクラスのインスタンスでない限り)。

そして、すでにshuuchanで述べられているように、a TreeSetはその実装でSetあり、順序が保証されています。

要素は、使用されるコンストラクターに応じて、自然な順序を使用して、またはセットの作成時に提供されるコンパレーターによって順序付けられます。


3

通常setは順序を維持しません。たとえば、すぐにemelentを見つけるためのHashSetですが、LinkedHashSetを試すと、入力した順序が維持されます。


1

2つの異なるものがあります。

  1. セット内の要素を並べ替えます。SortedSetと同様の実装があります。
  2. セットの挿入順序を維持します。LinkedHashSetおよびCopyOnWriteArraySet(スレッドセーフ)を使用できるもの。



-2

SortedSetの注文のみを行うことができますSet


問題は、挿入順(たまたまソートされる)を保持することです。
アッシリア2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.