web-dev-qa-db-ja.com

Javaのマップの浅いコピー

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

_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番目の方法が「未チェックのキャスト」警告を出すことです。そのため、@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();
}
_
103
dcp

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

Josh Bloch on Design-Copy Constructor vs Cloning

私の本でクローン作成に関する項目を読んだ場合、特に行間を読んだ場合、cloneが深く壊れていると思います。 [...] Cloneableが壊れているのは残念ですが、それは起こります。

Bloch(ちなみにCollectionフレームワークの設計と実装)は、「人々が期待するから」だけでclone()メソッドのみを提供していると言っています。彼は実際にそれを使用することをまったく勧めていません。


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

106

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

一方、Josh Blochが説明したように、clone()メソッドを使用することはお勧めできません。

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);
59
Luca Fagioli

実装を知らずにマップをコピーします。

static final Map shallowCopy(final Map source) throws Exception {
    final Map newMap = source.getClass().newInstance();
    newMap.putAll(source);
    return newMap;
}
11
Terris