2015-02-02 12 views
15

HashMap<Integer, List<MySpecialClass> >'un bir kopyasını almam gerekir, ancak kopyadaki bir şeyi değiştirdiğimde, orijinalin aynı kalmasını istiyorum. Yani, List<MySpecialClass>'dan birşeyi kopyadan kaldırdığımda, orijinalde List<MySpecialClass>'da kalıyor.Java'da HashMap'i (sığ kopya değil) kopyalama

mapCopy = new HashMap<>(originalMap); 
mapCopy = (HashMap) originalMap.clone(); 

Doğru muyum:

ben doğru anladıysam, bu iki yöntemin ne istiyorum olmadığı sadece sığ bir kopyasını oluşturmak?

Bunu yapmak, tüm anahtarlar ve tüm liste öğeleri arasında yinelemekten ve el ile kopyalamaktan daha iyi bir yol var mı?

cevap

11

Sığ bir kopyanın gereksinimlerinizi karşılamayacağı konusunda haklısınız. Bu orijinal haritadan List s kopyaları olacaktır, fakat birinden HashMap bir List bir değişiklik görünmesi bu List ler diğer HashMap karşılık gelen List yılında, aynı List nesnelere sevk edecektir.

Java bir HashMap için verilen hiçbir derin kopyalama yoktur, bu yüzden hala yeni HashMap tüm girdilere ve put onları döngü gerekecektir. Ancak, her seferinde List kopyasını da yapmalısınız. Böyle bir şey:

public static HashMap<Integer, List<MySpecialClass>> copy(
    HashMap<Integer, List<MySpecialClass>> original) 
{ 
    HashMap<Integer, List<MySpecialClass>> copy = new HashMap<Integer, List<MySpecialClass>>(); 
    for (Map.Entry<Integer, List<MySpecialClass>> entry : original.entrySet()) 
    { 
     copy.put(entry.getKey(), 
      // Or whatever List implementation you'd like here. 
      new ArrayList<MySpecialClass>(entry.getValue())); 
    } 
    return copy; 
} 

Eğer bireysel MySpecialClass nesneleri değiştirmek istiyor ve sizin HashMap kopyalanan arasında List s yansıtılmayacaktır değişiklikler, o zaman onları da yeni kopyalarını yapmak gerekecektir varsa

.

+0

For döngü bildirimi içinde copy.entrySet() yerine original.entrySet() bulunamaz mı? – Mathis

+0

@ user3394494 Evet, haklısınız. Sanırım kodu hızlı bir şekilde yazdığımda olan şey bu. Değiştirilmiş. – rgettman

1

HashMap'in kendisinin bir kopyasını oluşturuyorsunuz, bu nedenle HashMap kopyasını değiştirmek orijinal HashMap'i değiştirmeyecektir (yani giriş ekleme veya çıkarma), ancak sakladığınız nesneler ilkel türler olmadığından, Geri Aldığınız Listedir Verilen bir anahtar ile ilk veya ikinci Haritadan alındığında aynı olacaktır. Bu nedenle, her iki harita tarafından atıfta bulunulan bu listenin yalnızca bir kopyası var: Listeyi değiştirmek, hangi referansı kullandığınıza bakmaksızın değiştirir.

Gerçek Listenin ayrı bir kopya olmasını istiyorsanız, söylediğinizi yapmanız gerekir: HashMap'in giriş kümesinin üzerinde yineleyin ve her Listenin bir kopyasını el ile oluşturup, yeni haritayı sizinkine ekleyin. gitmek.

Bundan daha iyi bir yol varsa, bunun ne olduğunu bilmiyorum.

15

Maalesef bu yineleme gerektirir. Ama Java 8 akışları ile oldukça Önemsiz:

mapCopy = map.entrySet().stream() 
    .collect(Collectors.toMap(e -> e.getKey(), e -> new ArrayList(e.getValue())); 
+0

Akışlara aşina değilim. Çözümünüzü denediğimde bir hata verir: Statik olmayan getKey() yöntemi getValue() ile aynı statik bir bağlamdan referans alınamaz, nasıl düzenlenir, böylece çalışır? Teşekkürler – Mathis

+0

Üzgünüm - kodu düzeltirim. – sprinter

+0

Maalesef şu anda bir derleyicide değilim, bu yüzden test etme şansım olmadı. Bunu deneyin ve işe yaramazsa, test etme şansım olana kadar cevabı kaldıracağım. – sprinter

-1

serialize json ve sonradan serisini: özel sınıflar için size write a custom deserializer gerekebilir

Map<String, Object> originalMap = new HashMap<>(); 
String json = new Gson().toJson(originalMap); 
Map<String, Object> mapCopy = new Gson().fromJson(
    json, new TypeToken<Map<String, Object>>() {}.getType()); 

.

İlgili konular