자바에서 HashMap 복사
멤버를 포함하는 클래스의 임시 컨테이너를 유지하려고합니다.
HashMap<Integer,myObject> myobjectHashMap
myobjectsList라는 클래스
그럼 난
myojbectsListA = new myojbectsList();
myojbectsListB = new myobjectsList();
그런 다음 : A (like2)에 해시 맵 항목 추가
그때
myobjectListB = myobjectListA; //B has 2
그런 다음 : A에 해시 맵 항목을 추가합니다. (4 개 더 좋아요)
그런 다음 A를 B에 저장된 항목으로 되돌립니다.
myobjectListA = myobjectListb;
하지만이 작업을 수행하면 B가 A와 함께 성장하고 해시 맵 항목을 A에 추가합니다. 이제 B에 6이 있으므로 A에 6 개의 항목이 있습니다.
A가 C ++에서 마지막으로 어설 션 한 후에도 여전히 원본 2를 갖기를 원합니다. 객체와 함께 복사를 사용할 것입니다. Java에 해당하는 것은 무엇입니까?
추가됨 : OK. MyObjectsList에는 HashMap이 포함되어 있지 않으며, HashMap 멤버가 있고 MyObjectsList가 MyBaseOjbectsList를 확장하는 MyBaseOjbectsList 클래스에서 파생되었습니다. 이것이 차이를 만드는가.?
HashMap의 복사본을 원하면 새로운 것을 생성해야합니다.
myobjectListB = new HashMap<Integer,myObject>(myobjectListA);
이렇게하면지도의 (얕은) 사본이 생성됩니다.
당신은 또한 사용할 수 있습니다
clone()
한 해시 맵의 모든 요소를 다른 해시 맵으로 복사하는 방법
한 해시 맵에서 다른 해시 맵으로 모든 요소를 복사하는 프로그램
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);
}
}
차이점은 C ++에서는 객체가 스택에있는 반면 Java에서는 객체가 힙에 있다는 것입니다. A와 B가 객체 인 경우 Java에서는 언제든지 다음을 수행합니다.
B = A
A와 B는 동일한 객체를 가리 키므로 A에게하는 모든 작업은 B에게하고 그 반대의 경우도 마찬가지입니다.
HashMap()두 개의 다른 개체를 원하면 new를 사용하십시오 .
그리고 Map.putAll(...)두지도간에 데이터를 복사하는 데 사용할 수 있습니다 .
여기에 작은 (거대한) 과소 표현이 있습니다. 당신은 복사 할 경우 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");
}
}
}
따라서 기본적으로 여기와 같이 필드를 직접 복사해야합니다.
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);
Java에서 다음을 작성할 때 :
Object objectA = new Object();
Object objectB = objectA;
objectA과 objectB동일한 도면과 동일한 점이다. 하나를 변경하면 다른 것도 변경됩니다. 따라서 objectA(참조가 아닌) 상태를 변경하면 objectB해당 변경 사항도 반영됩니다.
그러나 다음과 같이 작성하면 :
objectA = new Object()
그런 다음 지금은 새 Object를 가리키면서 objectB만든 첫 번째 객체 (original objectA)를 objectA가리키고 있습니다.
이 질문은 아직 답이없고 비슷한 문제가 있었기 때문에 대답하려고 노력할 것입니다. 문제는 (다른 사람들이 이미 언급했듯이) 동일한 객체에 대한 참조를 복사하기 만하면 복사본을 수정하면 원본 객체도 수정된다는 것입니다. 그래서 당신이해야 할 일은 객체 (지도 값) 자체를 복사하는 것입니다. 그렇게하는 가장 쉬운 방법은 모든 객체가 직렬화 가능한 인터페이스를 구현하도록 만드는 것입니다. 그런 다음지도를 직렬화 및 역 직렬화하여 실제 복사본을 얻습니다. 직접 수행하거나 https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/에서 찾을 수있는 apache commons SerializationUtils # clone ()을 사용할 수 있습니다. lang / SerializationUtils.html 그러나 이것이 가장 간단한 접근 방식이지만 많은 객체를 직렬화하고 역 직렬화하는 것은 비용이 많이 드는 작업입니다.
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;
}
}
What you assign one object to another, all you're doing is copying the reference to the object, not the contents of it. What you need to do is take your object B and manually copy the contents of object A into it.
If you do this often, you might consider implementing a clone() method on the class that will create a new object of the same type, and copy all of it's contents into the new object.
Since the OP has mentioned he does not have access to the base class inside of which exists a HashMap - I am afraid there are very few options available.
One (painfully slow and resource intensive) way of performing a deep copy of an object in Java is to abuse the 'Serializable' interface which many classes either intentionally - or unintentionally extend - and then utilise this to serialise your class to ByteStream. Upon de-serialisation you will have a deep copy of the object in question.
A guide for this can be found here: https://www.avajava.com/tutorials/lessons/how-do-i-perform-a-deep-clone-using-serializable.html
Since Java 10 it is possible to use
Map.copyOf
for creating a shallow copy, which is also immutable. (Here is its Javadoc). For a deep copy, as mentioned in this answer you, need some kind of value mapper to make a safe copy of values. You don't need to copy keys though, since they must be immutable.
참고URL : https://stackoverflow.com/questions/10079266/copying-a-hashmap-in-java
'Programing' 카테고리의 다른 글
| 여러 테스트를위한 Unittest 설정 / 해체 (0) | 2020.08.10 |
|---|---|
| postgresql : INSERT INTO… (SELECT *…) (0) | 2020.08.10 |
| SQL Server Management Studio에서는 테이블에 인덱스를 추가 할 수 없습니다. (0) | 2020.08.09 |
| 마지막 git 커밋으로 롤백 (0) | 2020.08.09 |
| 헤더에 C ++ 인라인 함수가있는 이유는 무엇입니까? (0) | 2020.08.09 |