我试图保留一个包含成员的类的临时容器:
HashMap<Integer,myObject> myobjectHashMap
一个名为myobjectsList的类
然后我做
myojbectsListA = new myojbectsList();
myojbectsListB = new myobjectsList();
然后:将一些hashmap项添加到A(like2)
然后
myobjectListB = myobjectListA; //B has 2
然后:将哈希图项添加到A; (再多4个)
然后将A返回到存储在B;
中的项目myobjectListA = myobjectListb;
但是当我这样做时,B在A中增长,而我正在向A添加hashmap项目。 A现在有6个项目,因为B有6个。
我希望A在最后一次分配后仍然保持原来的2 在C ++中我会使用copy with objects,java等价物是什么?
补充:好的我没有解释这个问题.MyObjectsList不包含HashMap,它派生自MyBaseOjbectsList类,它具有HashMap成员,MyObjectsList扩展MyBaseOjbectsList。这有什么不同吗?
答案 0 :(得分:212)
如果您需要HashMap的副本,则需要使用。
构建一个新副本myobjectListB = new HashMap<Integer,myObject>(myobjectListA);
这将创建地图的(浅)副本。
答案 1 :(得分:14)
您也可以使用
clone()
将所有元素从一个散列映射复制到另一个散列映射的方法
将所有元素从一个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);
}
}
答案 2 :(得分:11)
不同之处在于,在C ++中,您的对象位于堆栈中,而在Java中,您的对象位于堆中。如果A和B是对象,那么在Java中的任何时候都可以:
B = A
A和B指向同一个对象,所以你对A做的任何事情都是对B做的,反之亦然。
如果您想要两个不同的对象,请使用新的HashMap()
。
您可以使用Map.putAll(...)
在两张地图之间复制数据。
答案 3 :(得分:6)
这里有一个小的(巨大的)轻描淡写。如果要复制带有嵌套结构的HashMap
,HashMap.putAll()
将通过引用进行复制,因为它不知道如何准确复制对象。 For example:
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");
}
}
}
所以基本上你需要像这里一样自己复制字段
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);
答案 4 :(得分:4)
在Java中,当你写:
Object objectA = new Object();
Object objectB = objectA;
objectA
和objectB
相同,并指向相同的参考。改变一个将改变另一个。因此,如果您更改objectA
的状态(不是其参考)objectB
也会反映出这种变化。
但是,如果你写:
objectA = new Object()
然后objectB
仍然指向您创建的第一个对象(原始objectA
),而objectA
现在指向一个新对象。
答案 5 :(得分:2)
由于这个问题仍然没有答案,我遇到了类似的问题,我将尝试回答这个问题。问题(正如其他人已经提到的)是您只是复制对同一对象的引用,因此对副本的修改也将修改原始对象。所以你需要的是复制对象(你的地图值)本身。最简单的方法是使所有对象实现可序列化的接口。然后序列化和反序列化您的地图以获得真实副本。您可以自己执行此操作或使用apache commons SerializationUtils#clone(),您可以在此处找到它:https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/SerializationUtils.html但请注意,这是最简单的方法,但序列化和反序列化大量对象是一项昂贵的任务。
答案 6 :(得分:1)
如果要使用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;
}
此方法使用Stream.collect()
方法创建克隆映射,但使用的方法与以前的方法相同。
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())));
}
但是,如果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;
}
}
答案 7 :(得分:0)
您将一个对象分配给另一个对象,您所做的只是将引用复制到对象,而不是它的内容。您需要做的是获取对象B并手动将对象A的内容复制到其中。
如果经常这样做,您可以考虑在类上实现一个clone()
方法,该方法将创建一个相同类型的新对象,并将其所有内容复制到新对象中。
答案 8 :(得分:0)
由于OP提到他无法访问其中存在HashMap的基类-恐怕可用的选项很少。
在Java中执行对象的深层副本的一种(非常慢且耗费大量资源的)方法是滥用“ Serializable”接口,该接口许多类有意(或无意地)扩展了它们,然后利用该接口将您的类序列化为ByteStream 。反序列化后,您将获得有关对象的深层副本。
有关此问题的指南,请参见:https://www.avajava.com/tutorials/lessons/how-do-i-perform-a-deep-clone-using-serializable.html
答案 9 :(得分:0)
自Java 10起,就可以使用
Map.copyOf
用于创建浅副本,该副本也是不变的。 (这是它的Javadoc)。如本answer you所述,对于深层副本,需要某种类型的值映射器来制作值的安全副本。不过,您不必复制键,因为它们必须是不可变的。
答案 10 :(得分:0)
Java支持浅(非深层)复制概念
您可以使用以下方式对其进行存档:
clone()
putAll()