在Java中复制HashMap

use*_*305 109 java clone copy hashmap

我试图保持包含成员的类的临时容器:

HashMap<Integer,myObject> myobjectHashMap
Run Code Online (Sandbox Code Playgroud)

一个名为myobjectsList的类

然后我做

myojbectsListA = new myojbectsList();
myojbectsListB = new myobjectsList();
Run Code Online (Sandbox Code Playgroud)

然后:将一些hashmap项添加到A(like2)

然后

myobjectListB = myobjectListA; //B has 2
Run Code Online (Sandbox Code Playgroud)

然后:将hashmap项添加到A; (还有4个)

然后将A返回到存储在B中的项目;

myobjectListA = myobjectListb;
Run Code Online (Sandbox Code Playgroud)

但是当我这样做的时候,B在A中增长,而我正在向A添加hashmap项目.A现在有6个项目,因为B有6个.

我希望A在C++的最后一次分配之后仍然有原始的2,我将使用副本与对象,什么是Java等价物?

补充:好的我没有解释这个问题.MyObjectsList不包含HashMap,它来自一个具有HashMap成员的MyBaseOjbectsList类,MyObjectsList扩展了MyBaseOjbectsList.这有什么不同吗?

rat*_*eak 216

如果你想要一个HashMap的副本,你需要构建一个新的.

myobjectListB = new HashMap<Integer,myObject>(myobjectListA);
Run Code Online (Sandbox Code Playgroud)

这将创建地图的(浅)副本.

  • @Kevin Welker,`addAll`用于`HashSet`.`putAll`用于`HashMap`. (8认同)
  • 或者如果已经创建,请使用`myObjectListB.addAll(myObjectListA)` (4认同)
  • @Thomio我提到过,这就是"浅拷贝"的意思,如果你需要深拷贝来遍历地图并复制你需要的东西. (4认同)
  • 没用 在我的情况下,“新”变量仍指向同一对象。 (2认同)

小智 15

你也可以使用

clone()
Run Code Online (Sandbox Code Playgroud)

将所有元素从一个散列映射复制到另一个散列映射的方法

用于将所有元素从一个hashmap复制到另一个hashmap的程序

import java.util.HashMap;

public class CloneHashMap {    
     public static void main(String a[]) {    
        HashMap hashMap = new HashMap();    
        HashMap hashMap1 = new HashMap();    
        hashMap.put(1, "One");
        hashMap.put(2, "Two");
        hashMap.put(3, "Three");
        System.out.println("Original HashMap : " + hashMap);
        hashMap1 = (HashMap) hashMap.clone();
        System.out.println("Copied HashMap : " + hashMap1);    
    }    
}
Run Code Online (Sandbox Code Playgroud)

来源:http: //www.tutorialdata.com/examples/java/collection-framework/hashmap/copy-all-elements-from-one-hashmap-to-another

  • 你可以,但是你可能不应该因为克里斯伯特基本上是破碎的,根据约书亚布洛赫的有效Java#11. (13认同)
  • 另请注意,clone()返回一个浅表副本. (11认同)
  • 什么浅甚至意味着什么?如果它没有完全复制地图(键/值保持不变),为什么要这么麻烦?不妨创建一张新地图吧? (3认同)
  • @Azurespot 浅意味着它不会复制任何嵌套对象及其嵌套对象... (3认同)
  • 如果查看源代码,所有clone()都会创建一个新的`HashMap`和`putAll`.这完全没有意义. (2认同)

Con*_*Del 11

不同之处在于,在C++中,您的对象位于堆栈中,而在Java中,您的对象位于堆中.如果A和B都是对象,那么你可以随时使用java

B = A.

A和B指向SAME对象.所以你对A做的任何事情都要做到B,反之亦然

如果你想要两个不同的对象,请使用新的HashMap()

您可以使用Map.putAll(...)在两个地图之间复制数据


mur*_*urt 6

这里有一个小的(巨大的)轻描淡写.如果要复制HashMap带嵌套结构的嵌入式结构,HashMap.putAll()将通过引用进行复制,因为它不知道如何精确复制对象.例如:

import java.util.*;
class Playground {
    public static void main(String[ ] args) {
        Map<Integer, Map<Integer,List<Float>>> dataA = new HashMap<>();
        Map<Integer, Map<Integer,List<Float>>> dataB = new HashMap<>();

        dataA.put(1, new HashMap<>());
        dataB.putAll(dataA);

        assert(dataB.get(1).size() == 0);

        dataA.get(1).put(2, new ArrayList<>());

        if (dataB.get(1).size() == 1) { // true
            System.out.println(
                "Sorry object reference was copied - not the values");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以基本上你需要像这里一样自己复制字段

List <Float> aX = new ArrayList<>(accelerometerReadingsX);
List <Float> aY = new ArrayList<>(accelerometerReadingsY);

List <Float> gX = new ArrayList<>(gyroscopeReadingsX);
List <Float> gY = new ArrayList<>(gyroscopeReadingsY);

Map<Integer, Map<Integer, Float>> readings = new HashMap<>();

Map<Integer,List<Float>> accelerometerReadings = new HashMap<>();
accelerometerReadings.put(X_axis, aX);
accelerometerReadings.put(Y_axis, aY);
readings.put(Sensor.TYPE_ACCELEROMETER, accelerometerReadings);

Map<Integer,List<Float>> gyroscopeReadings = new HashMap<>();
gyroscopeReadings.put(X_axis, gX);
gyroscopeReadings.put(Y_axis, gY);
readings.put(Sensor.TYPE_GYROSCOPE, gyroscopeReadings);
Run Code Online (Sandbox Code Playgroud)


Teo*_*cci 5

如果我们想在 Java 中复制一个对象,我们需要考虑两种可能性:浅拷贝深拷贝

浅拷贝是,当我们只复制字段值的方法。因此,副本可能依赖于原始对象。在深度复制方法中,我们确保树中的所有对象都被深度复制,因此副本不依赖于任何可能会更改的先前存在的对象。

这个问题是深拷贝方法应用的完美定义。

首先,如果您有一个简单的HashMap<Integer, List<T>>地图,那么我们只需创建一个像这样的解决方法。创建List<T>.

public static <T> HashMap<Integer, List<T>> deepCopyWorkAround(HashMap<Integer, List<T>> original)
{
    HashMap<Integer, List<T>> copy = new HashMap<>();
    for (Map.Entry<Integer, List<T>> entry : original.entrySet()) {
        copy.put(entry.getKey(), new ArrayList<>(entry.getValue()));
    }
    return copy;
}
Run Code Online (Sandbox Code Playgroud)

这个是使用Stream.collect()method来创建clone map,但是使用的思路和之前的方法一样。

public static <T> Map<Integer, List<T>> deepCopyStreamWorkAround(Map<Integer, List<T>> original)
{
    return original
            .entrySet()
            .stream()
            .collect(Collectors.toMap(Map.Entry::getKey, valueMapper -> new ArrayList<>(valueMapper.getValue())));
}   
Run Code Online (Sandbox Code Playgroud)

但是,如果里面的实例T也是可变对象,我们就会遇到大问题。在这种情况下,真正的深拷贝是解决此问题的替代方案。它的优点是至少对象图中的每个可变对象都被递归复制。由于副本不依赖于之前创建的任何可变对象,因此它不会像我们在浅拷贝中看到的那样被意外修改。

为了解决这个深拷贝实现将完成的工作。

public class DeepClone
{
    public static void main(String[] args)
    {
        Map<Long, Item> itemMap = Stream.of(
                entry(0L, new Item(2558584)),
                entry(1L, new Item(254243232)),
                entry(2L, new Item(986786)),
                entry(3L, new Item(672542)),
                entry(4L, new Item(4846)),
                entry(5L, new Item(76867467)),
                entry(6L, new Item(986786)),
                entry(7L, new Item(7969768)),
                entry(8L, new Item(68868486)),
                entry(9L, new Item(923)),
                entry(10L, new Item(986786)),
                entry(11L, new Item(549768)),
                entry(12L, new Item(796168)),
                entry(13L, new Item(868421)),
                entry(14L, new Item(923)),
                entry(15L, new Item(986786)),
                entry(16L, new Item(549768)),
                entry(17L, new Item(4846)),
                entry(18L, new Item(4846)),
                entry(19L, new Item(76867467)),
                entry(20L, new Item(986786)),
                entry(21L, new Item(7969768)),
                entry(22L, new Item(923)),
                entry(23L, new Item(4846)),
                entry(24L, new Item(986786)),
                entry(25L, new Item(549768))
        ).collect(entriesToMap());


        Map<Long, Item> clone = DeepClone.deepClone(itemMap);
        clone.remove(1L);
        clone.remove(2L);

        System.out.println(itemMap);
        System.out.println(clone);
    }

    private DeepClone() {}

    public static <T> T deepClone(final T input)
    {
        if (input == null) return null;

        if (input instanceof Map<?, ?>) {
            return (T) deepCloneMap((Map<?, ?>) input);
        } else if (input instanceof Collection<?>) {
            return (T) deepCloneCollection((Collection<?>) input);
        } else if (input instanceof Object[]) {
            return (T) deepCloneObjectArray((Object[]) input);
        } else if (input.getClass().isArray()) {
            return (T) clonePrimitiveArray((Object) input);
        }

        return input;
    }

    private static Object clonePrimitiveArray(final Object input)
    {
        final int length = Array.getLength(input);
        final Object output = Array.newInstance(input.getClass().getComponentType(), length);
        System.arraycopy(input, 0, output, 0, length);
        return output;
    }

    private static <E> E[] deepCloneObjectArray(final E[] input)
    {
        final E[] clone = (E[]) Array.newInstance(input.getClass().getComponentType(), input.length);
        for (int i = 0; i < input.length; i++) {
            clone[i] = deepClone(input[i]);
        }

        return clone;
    }

    private static <E> Collection<E> deepCloneCollection(final Collection<E> input)
    {
        Collection<E> clone;
        if (input instanceof LinkedList<?>) {
            clone = new LinkedList<>();
        } else if (input instanceof SortedSet<?>) {
            clone = new TreeSet<>();
        } else if (input instanceof Set) {
            clone = new HashSet<>();
        } else {
            clone = new ArrayList<>();
        }

        for (E item : input) {
            clone.add(deepClone(item));
        }

        return clone;
    }

    private static <K, V> Map<K, V> deepCloneMap(final Map<K, V> map)
    {
        Map<K, V> clone;
        if (map instanceof LinkedHashMap<?, ?>) {
            clone = new LinkedHashMap<>();
        } else if (map instanceof TreeMap<?, ?>) {
            clone = new TreeMap<>();
        } else {
            clone = new HashMap<>();
        }

        for (Map.Entry<K, V> entry : map.entrySet()) {
            clone.put(deepClone(entry.getKey()), deepClone(entry.getValue()));
        }

        return clone;
    }
}
Run Code Online (Sandbox Code Playgroud)


xue*_*eng 5

从 Java 10 开始,可以使用

Map.copyOf
Run Code Online (Sandbox Code Playgroud)

用于创建浅拷贝,它也是不可变的。(这是它的Javadoc)。对于深拷贝,如本答案中所述,需要某种值映射器来制作值的安全副本。不过,您不需要复制密钥,因为它们必须是不可变的


ass*_*ias 4

在Java中,当你写:

Object objectA = new Object();
Object objectB = objectA;
Run Code Online (Sandbox Code Playgroud)

objectAobjectB是相同的并且指向相同的参考。改变一个就会改变另一个。objectA因此,如果您更改(而不是其引用)的状态objectB也会反映该更改。

但是,如果你写:

objectA = new Object()
Run Code Online (Sandbox Code Playgroud)

然后objectB仍然指向您创建的第一个对象(原始objectA),而objectA现在指向一个新对象。