109

Map私が理解しているように、Javaで a の浅いコピーを作成するには、いくつかの方法があります(おそらく他の方法も) :

Map<String, Object> data = new HashMap<String, Object>();
Map<String, Object> shallowCopy;

// first way
shallowCopy = new HashMap<String, Object>(data);

// second way
shallowCopy = (Map<String, Object>) ((HashMap<String, Object>) data).clone();

ある方法が他の方法よりも優先されますか? もしそうなら、それはなぜですか?

言及する価値のあることの 1 つは、2 番目の方法では「Unchecked Cast」という警告が表示されることです。そのため、それを回避するために追加@SuppressWarnings("unchecked")する必要がありますが、これは少しイライラします (以下を参照)。

@SuppressWarnings("unchecked")
public Map<String, Object> getDataAsMap() {
    // return a shallow copy of the data map
    return (Map<String, Object>) ((HashMap<String, Object>) data).clone();
}
4

3 に答える 3

107

コピー コンストラクターを使用してコピーすることをお勧めします。clone()in Java は壊れています (SO:クローン メソッドを適切にオーバーライドするには? を参照してください)。

Josh Bloch on Design - コピー コンストラクターとクローン作成

私の本でクローンに関する項目を読んだことがあるなら、特に行間を読んだなら、私cloneが深く壊れていると思うことがわかるでしょう。Cloneable[...]壊れているのは残念ですが、起こります。

Bloch (ちなみに Collection フレームワークを設計および実装した人物) はさらに、clone()「人々がそれを期待しているから」メソッドを提供しているだけだと述べています。彼は実際にそれを使用することをまったく推奨していません.


より興味深い議論は、コピー コンストラクターがコピー ファクトリよりも優れているかどうかだと思いますが、それはまったく別の議論です。

于 2010-03-01T15:27:31.000 に答える
61

2 つのどちらでもない:参照しているコンストラクターは、 MapのHashMap実装(および他のもの) に対して定義されていますが、 Map インターフェース自体に対しては定義されていません (たとえば、 Map インターフェースのProvider実装を検討してください:そのコンストラクターは見つかりません)。

一方、clone()Josh Bloch が説明しているように、この方法を使用することはお勧めできません。

Map インターフェイス (および HashMap ではなく Map をコピーする方法を尋ねる質問) に関しては、Map#putAll()を使用する必要があります。

指定されたマップからこのマップにすべてのマッピングをコピーします (オプションの操作)。この呼び出しの効果は、指定されたマップのキー k から値 v へのマッピングごとに、このマップで put(k, v) を 1 回呼び出すのと同じです。

例:

// HashMap here, but it works for every implementation of the Map interface
Map<String, Object> data = new HashMap<String, Object>();
Map<String, Object> shallowCopy = new HashMap<String, Object>();

shallowCopy.putAll(data);
于 2013-02-01T17:28:36.003 に答える