0

次のコードがあるとします。

List<String> modifiableList = new ArrayList<String>(Arrays.asList("1","2","3"));
List<String> unmodifiableList = Collections.unmodifiableList(modifiableList);
System.out.println(unmodifiableList);
modifiableList.remove("1");
modifiableList.remove("3");
System.out.println(unmodifiableList);

それは印刷します

[1, 2, 3]
[2]

2 行目を次のように変更する場合

List<String> unmodifiableList = Collections.unmodifiableList(
                                       new ArrayList<String>(modifiableList));

期待どおりに動作します。問題は、UnmodifiableListコレクションの内部クラス (および他のすべての変更不可能なクラス) が元のリストの新しいコピーを作成しないのはなぜArrayListですか?

編集:コードの機能を理解しています。私の質問は、なぜこのように実装されたのですか? 基になる配列の新しいコピーを作成する際に、UnmodifiableList (コレクションの内部クラス) のコンストラクターが ArrayList のコンストラクターのように動作するのはなぜですか? 変更可能なコレクション (ArrayList) はコンテンツ全体をコピーするのに、変更不可能なコレクションはコピーしないのはなぜですか?

4

3 に答える 3

2

理由は単純に効率です。コレクションのすべての要素をコピーすると、非常に時間がかかる可能性があります。特に、ラップされているコレクションに JPA 遅延読み込みなどの魔法がかかっていて、余分なメモリが必要な場合はそうです。基礎となるコレクションをそのままラップすることは、追加のオーバーヘッドを課さない簡単な操作です。開発者が本当に別のコピー (変更不可または不可) を必要とする場合、明示的に作成するのは非常に簡単です。(私はこれにグアバを使用する傾向がありますImmutable*。)

于 2014-02-06T13:29:28.997 に答える
2

メソッドの目的は、既存のコレクションに変更不可能なビューを作成することです。それは文書化された動作であり、多くの場合、それはまさにあなたが望むものです-たとえば、すべてのデータをコピーするよりもはるかに効率的です...または、必要な変更を反映する呼び出し元のコレクションを渡したいが、それらを変更してください。

データ(または少なくとも参照...)の不変のコピーが必要な場合は、コピーを作成し、その上に不変のビューを作成します-そのままです。

Collections.unmodifiable*したがって、基本的には、ビュー操作の実行に基づいて、ビューまたはコピー アンド ビューを簡単に作成できます。したがって、2 つの直交演算があります。

  • コピーを作成します (例: コンストラクター経由)
  • ビューを作成する (経由Collections.unmodifiable*)

これらの操作は非常に簡単に構成できます。Collections.unmodifiable*実際に「コピーのみ」を実行した場合、ビューを作成するために他の操作が必要になります。両方のオプションがさまざまな状況で役立つことを受け入れる場合は、それらを構成可能にすることで多くの柔軟性が得られます。

于 2014-02-06T13:30:00.810 に答える