web-dev-qa-db-ja.com

Java不変コレクション

Java 1.6 Collection Frameworkドキュメント から:

変更操作をサポートしないコレクション(addremoveclearなど)は、unmodifiableと呼ばれます。 [...] Collectionオブジェクトの変更が表示されないことをさらに保証するコレクションは、immutableと呼ばれます。

2番目の基準は少し混乱します。最初のコレクションは変更不可能であり、元のコレクション参照が破棄されたと仮定すると、2行目で参照される変更は何ですか?コレクションに保持されている要素の変更、つまり要素の状態を参照していますか?

2番目の質問:
コレクションを不変にするために、指定された追加の保証人をどのように提供しますか?コレクション内の要素の状態がスレッドによって更新された場合、状態のそれらの更新が不変コレクションを保持するスレッド上で見えないのは不変性にとって十分ですか?

コレクションを不変にするために、指定された追加の保証人をどのように提供しますか?

107
Bhaskar

変更不可能なコレクションは、通常、他のコレクションの読み取り専用ビュー(ラッパー)です。それらを追加、削除、またはクリアすることはできませんが、基になるコレクションは変更できます。

不変コレクションはまったく変更できません-別のコレクションをラップしません-独自の要素を持っています。

グアバの ImmutableList からの引用です

変更可能な別のコレクションのビューであるCollections.unmodifiableList(Java.util.List<? extends T>)とは異なり、ImmutableListのインスタンスには独自のプライベートデータが含まれており、変更されることはありません。

したがって、基本的に、変更可能なコレクションから不変のコレクションを取得するには、その要素を新しいコレクションにコピーし、すべての操作を禁止する必要があります。

146
Bozho

違いは、変更を許可する不変のコレクションへの参照ができないことです。変更不可能なコレクションは変更できませんその参照を介してですが、他のオブジェクトは変更可能な同じデータを指す場合があります。

例えば.

List<String> strings = new ArrayList<String>();
List<String> unmodifiable = Collections.unmodifiableList(strings);
unmodifiable.add("New string"); // will fail at runtime
strings.add("Aha!"); // will succeed
System.out.println(unmodifiable);
84
Simon Nickerson
Collection<String> c1 = new ArrayList<String>();
c1.add("foo");
Collection<String> c2 = Collections.unmodifiableList(c1);

c1mutable(つまりunmodifiable不変)。
c2unmodifiable:それ自体は変更できませんが、後でc1を変更した場合that変更はc2に表示されます。

これは、c2c1の単なるラッパーであり、実際には独立したコピーではないためです。 Guavaは ImmutableList interface といくつかの実装を提供します。これらは、入力のコピーを実際に作成することで機能します(入力がそれ自体で不変のコレクションでない場合)。

2番目の質問について:

コレクションの可変性/不変性は、含まれるオブジェクトの可変性/不変性に依存しますnot。コレクションに含まれるオブジェクトを変更すると、この説明では「コレクションの変更」としてnotカウントされます。もちろん、不変のコレクションが必要な場合、通常はも不変のオブジェクトを含むようにします。

19
Joachim Sauer

Java 9には、不変のList、Set、Map、およびMap.Entryのファクトリメソッドがあります。

Java SE 8以前のバージョンでは、unmodifiableXXXなどのコレクションクラスユーティリティメソッドを使用して、不変のコレクションオブジェクトを作成できます。

ただし、これらのCollections.unmodifiableXXXメソッドは非常に退屈で冗長なアプローチです。これらの欠点を克服するために、Oracle corpは、List、Set、およびMapインターフェイスにいくつかのユーティリティメソッドを追加しました。

Now in Java 9:- ListおよびSetインターフェースには、以下に示すように空または空でない不変のListまたはSetオブジェクトを作成するための“ of()”メソッドがあります。

空のリストの例

List immutableList = List.of();

空でないリストの例

List immutableList = List.of("one","two","three");
14
Vijay Gupta

ここでのポイントは、コレクションが変更不可であっても、それが変更できないことを保証しないということだと思います。例えば、要素が古すぎる場合にそれらを排除するコレクションを考えてみましょう。変更不可能とは、参照を保持するオブジェクトが変更できないことを意味し、変更できないことを意味しません。これの本当の例はCollections.unmodifiableListメソッドです。リストの変更不可能なビューを返します。このメソッドに渡されたリスト参照は引き続き変更可能であるため、渡された参照の所有者はリストを変更できます。これにより、ConcurrentModificationExceptionsおよびその他の問題が発生する可能性があります。

不変、つまりコレクションを変更できないことを意味します。

2番目の質問:不変コレクションは、コレクションに含まれるオブジェクトが変更されないことを意味するのではなく、そのコレクションが保持するオブジェクトの数と構成が変更されないだけです。つまり、コレクションの参照リストは変更されません。それは、参照されているオブジェクトの内部が変更できないという意味ではありません。

6
John B

Pure4J は、次の2つの方法で目的をサポートします。

最初に、@ImmutableValue注釈を提供します。これにより、クラスに注釈を付けて、不変であることを示すことができます。コードが実際に不変(finalなどの使用)であることを確認できるmavenプラグインがあります。

第二に、Clojureから永続コレクションを提供し(ジェネリックを追加)、コレクションに追加された要素が不変であることを保証します。これらのパフォーマンスは明らかにかなり良いです。コレクションはすべて不変ですが、検査のためにJavaコレクションインターフェイス(およびジェネリック)を実装します。突然変異は新しいコレクションを返します。

免責事項:私はこれの開発者です

0
Rob Moffat