web-dev-qa-db-ja.com

Collections.unmodifiableSet()とGuavaのImmutableSetの違いは何ですか?

ImmutableSetのJavaDocはこう言っています:

変更可能な個別のコレクションのビューである_Collections.unmodifiableSet_とは異なり、このクラスのインスタンスには独自のプライベートデータが含まれ、変更されることはありません。このクラスはパブリックスタティックファイナルセット( "定数セット」)と、呼び出し元からクラスに提供されたセットの「防御コピー」を簡単に作成することもできます。

しかし、ImmutableSetにはまだ要素の参照が格納されているため、Collections.unmodifiableSet()との違いを理解できませんでした。サンプル:

_StringBuffer s=new StringBuffer("a");
ImmutableSet<StringBuffer> set= ImmutableSet.of(s);
s.append("b");//s is "ab", s is still changed here!
_

誰かそれを説明できますか?

このことを考慮:

Set<String> x = new HashSet<String>();
x.add("foo");

ImmutableSet<String> guava = ImmutableSet.copyOf(x);
Set<String> builtIn = Collections.unmodifiableSet(x);

x.add("bar");
System.out.println(guava.size()); // Prints 1
System.out.println(builtIn.size()); // Prints 2

言い換えると、ImmutableSetは、コピーが作成されるため、変更された可能性があるものから構築されたコレクションに関係なく不変です。 Collections.unmodifiableSetreturnedコレクションが直接変更されるのを防ぎますが、それでも潜在的に変化するバッキングセットのビューです。

オブジェクトの内容の変更を開始した場合、任意のセットでreferredに変更しても、すべてのベットはとにかくオフになります。それをしないでください。実際、最初に変更可能な要素型を使用してセットを作成することは、めったにありません。 (可変キータイプを使用した同上マップ。)

89
Jon Skeet

Jonが言及している動作の違いに加えて、ImmutableSetCollections.unmodifiableSetによって作成されたSetの重要な違いは、ImmutableSettypeであることです。コード全体でImmutableSetではなくSetを使用して、セットが不変であることを明確にしておくことができます。 Collections.unmodifiableSetを使用すると、返されるタイプはSet...なので、Setを渡すすべての場所にJavadocを追加しない限り、セットが作成された時点でセットを変更できないことは明らかです。

21
ColinD

Kevin Bourrillion(Guavaのリード開発者)が、不変/変更不可能なコレクションを このプレゼンテーション で比較します。プレゼンテーションは2年前のもので、「グーバ」のサブパートである「Googleコレクション」に焦点を当てていますが、これは非常に興味深いプレゼンテーションです。 APIはあちこちで変更されている可能性がありますが(Google Collections APIは当時ベータ版でした)、Google Collections/Guavaの背後にある概念はまだ有効です。

this other SO questiongoogleのImmutableListとCollections.unmodifiableList()の違いは何ですか?).

10
Etienne Neveu

他の回答で述べられていない2つの違いは、 Javadoc で説明されているように、ImmutableSetnull値を許可しないことです

信頼性の高い、ユーザー指定の反復順序を備えた高性能で不変のセット。 null要素は許可されません。

(同じ制限がすべてのGuava不変コレクションの値に適用されます。)

例えば:

ImmutableSet.of(null);
ImmutableSet.builder().add("Hi").add(null); // Fails in the Builder.
ImmutableSet.copyOf(Arrays.asList("Hi", null));

これらはすべて実行時に失敗します。対照的に:

Collections.unmodifiableSet(new HashSet<>(Arrays.asList("Hi", null)));

これで結構です。

3
Andy Turner