J'essaie de conserver un conteneur temporaire d'une classe qui contient member:
HashMap<Integer,myObject> myobjectHashMap
Une classe appelée myobjectsList
Alors je fais
myojbectsListA = new myojbectsList();
myojbectsListB = new myobjectsList();
then: Ajouter des éléments de hashmap à A (like2)
ensuite
myobjectListB = myobjectListA; //B has 2
puis: Ajoutez des éléments hashmap à A; (comme 4 de plus)
retournez ensuite A aux éléments stockés dans B;
myobjectListA = myobjectListb;
mais quand je fais cela, B grandit avec A tandis que j'ajoute des éléments hashmap à A. A contient maintenant 6 éléments, car B en avait 6.
Je veux que l'original 2 soit toujours à la fin après le dernier relevé en C++. J'utiliserais la copie avec des objets. Quel est l'équivalent Java?
Ajouté: OK J'ai laissé quelque chose pour expliquer cela. MyObjectsList ne contient pas HashMap, il est dérivé d'une classe MyBaseOjbectsList qui comprend le membre HashMap et MyObjectsList étend MyBaseOjbectsList. Cela fait-il une différence?
Si vous voulez une copie de HashMap, vous devez en créer une nouvelle avec.
myobjectListB = new HashMap<Integer,myObject>(myobjectListA);
Cela créera une copie (peu profonde) de la carte.
Vous pouvez aussi utiliser
clone()
Méthode pour copier tous les éléments d'un hashmap vers un autre hashmap
Programme pour copier tous les éléments d'un hashmap à un autre
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);
}
}
La différence réside dans le fait qu'en C++, votre objet se trouve sur la pile, alors qu'en Java, il se trouve dans le tas. Si A et B sont des objets, à tout moment dans Java:
B = A
A et B pointent sur le même objet, donc tout ce que vous faites à A vous faites à B et vice versa.
Utilisez new HashMap()
si vous voulez deux objets différents.
Et vous pouvez utiliser Map.putAll(...)
pour copier des données entre deux cartes.
Il y a un petit euphorique (énorme) ici. Si vous voulez copier un HashMap
avec des structures imbriquées, HashMap.putAll()
le copiera par référence, car il ne sait pas exactement comment copier votre objet. Par exemple:
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");
}
}
}
Donc, fondamentalement, vous devrez copier les champs vous-même comme ici
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);
En Java, quand vous écrivez:
Object objectA = new Object();
Object objectB = objectA;
objectA
et objectB
sont identiques et indiquent la même référence. Changer l'un changera l'autre. Donc, si vous changez l'état de objectA
(pas sa référence) _ objectB
reflétera également ce changement.
Cependant, si vous écrivez:
objectA = new Object()
Ensuite, objectB
pointe toujours sur le premier objet que vous avez créé (original objectA
) alors que objectA
pointe maintenant sur un nouvel objet.
Comme cette question est toujours sans réponse et que j'avais un problème similaire, je vais essayer d'y répondre. Le problème (comme d’autres déjà mentionnés) est que vous copiez simplement des références dans le même objet et qu’une modification sur la copie modifiera également l’objet Origin. Vous devez donc copier l'objet (votre valeur de carte) lui-même. Le moyen le plus simple consiste à faire en sorte que tous vos objets implémentent l'interface sérialisable. Ensuite, sérialisez et désérialisez votre carte pour en obtenir une copie réelle. Vous pouvez le faire vous-même ou utiliser le SerializationUtils # clone () d'Apache commons que vous pouvez trouver ici: https://commons.Apache.org/proper/commons-lang/javadocs/api-2.6/org/ Apache/commons/lang/SerializationUtils.html Sachez que c’est l’approche la plus simple, mais c’est une tâche coûteuse de sérialiser et de désérialiser beaucoup d’objets.
Si nous voulons copier un objet en Java, nous devons envisager deux possibilités: a copie superficielle et une copie complète.
Le copie superficielle est l'approche utilisée lorsque nous copions uniquement les valeurs de champ. Par conséquent, la copie peut dépendre de l'objet d'origine. Dans l'approche copie profonde, nous nous assurons que tous les objets de l'arborescence sont copiés en profondeur, de sorte que la copie ne dépend d'aucun objet existant antérieur susceptible de changer.
Cette question est la définition parfaite pour l’application de l’approche copie profonde.
Premièrement, si vous avez une simple carte HashMap<Integer, List<T>>
, nous créons simplement une solution de contournement comme celle-ci. Création d'une nouvelle instance de 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;
}
Celui-ci utilise la méthode Stream.collect()
pour créer la carte de clonage, mais utilise la même idée que la méthode précédente.
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())));
}
Mais, si les instances à l'intérieur de T
sont également objets mutables, nous avons un gros problème. Dans ce cas, une copie profonde réelle est une alternative qui résout ce problème. Son avantage est qu'au moins chaque objet mutable dans le graphe d'objet est copié de manière récursive. Comme la copie ne dépend d’aucun objet mutable créé précédemment, elle ne sera pas modifiée par accident, comme nous l’avons vu avec la copie superficielle.
Pour résoudre le problème, cette implémentation en copie profonde fera le travail.
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;
}
}
Depuis Java 10, il est possible d'utiliser
Map.copyOf
pour créer une copie peu profonde , qui est également immuable. (Voici sa Javadoc ). Pour une copie complète , comme mentionné dans ce répondre , vous avez besoin d'un mappeur de valeurs pour créer une copie sécurisée des valeurs . Vous n'avez pas besoin de copier les clés , car elles doivent être immuables .
Depuis que le PO a indiqué qu’il n’avait pas accès à la classe de base à l’intérieur de laquelle existe un HashMap - j’ai bien peur que très peu d’options soient disponibles.
Un moyen (extrêmement lent et gourmand en ressources) d’effectuer une copie complète d’un objet dans Java consiste à abuser de l’interface 'Serializable', que de nombreuses classes étendent intentionnellement - ou involontairement -, puis l’utilisent pour sérialiser votre contenu. classe à ByteStream. Lors de la désérialisation, vous aurez une copie complète de l'objet en question.
Un guide pour cela peut être trouvé ici: https://www.avajava.com/tutorials/lessons/how-do-i-perform-a-deep-clone-using-serializable.html
Ce que vous attribuez à un objet, tout ce que vous faites est de copier le référence vers l’objet, pas son contenu. Ce que vous devez faire, c'est prendre votre objet B et copier manuellement le contenu de l'objet A dans celui-ci.
Si vous le faites souvent, vous pouvez envisager d'implémenter une méthode clone()
sur la classe qui créera un nouvel objet du même type et copiera tout son contenu dans le nouvel objet.