web-dev-qa-db-fra.com

Copie superficielle d'une carte dans Java

Si je comprends bien, il existe deux manières (peut-être d'autres également) de créer une copie superficielle d'un Map en Java:

Map<String, Object> data = new HashMap<String, Object>();
Map<String, Object> shallowCopy;

// first way
shallowCopy = new HashMap<String, Object>(data);

// second way
shallowCopy = (Map<String, Object>) ((HashMap<String, Object>) data).clone();

Un moyen est-il préférable à un autre, et si oui, pourquoi?

Une chose à noter est que la deuxième façon donne un avertissement "Distribution incontrôlée". Il faut donc ajouter @SuppressWarnings("unchecked") pour la contourner, ce qui est un peu irritant (voir ci-dessous).

@SuppressWarnings("unchecked")
public Map<String, Object> getDataAsMap() {
    // return a shallow copy of the data map
    return (Map<String, Object>) ((HashMap<String, Object>) data).clone();
}
103
dcp

Il est toujours préférable de copier en utilisant un constructeur de copie. clone() in Java est cassé (voir SO: Comment redéfinir correctement la méthode de clonage? ).

Josh Bloch sur Design - Constructeur de copie versus clonage

Si vous avez lu l'article sur le clonage dans mon livre, en particulier si vous lisez entre les lignes, vous saurez que je pense que clone est profondément brisé. [...] Dommage que Cloneable soit cassé, mais cela arrive.

Bloch (qui a d'ailleurs conçu et implémenté le framework Collection) est même allé plus loin en déclarant qu'il ne fournissait que la méthode clone() simplement "parce que les gens l'attendent". Il ne recommande PAS réellement de l'utiliser du tout.


Je pense que le débat le plus intéressant est de savoir si un constructeur de copie est préférable à une usine de copie, mais c'est une discussion totalement différente.

106

Aucune des deux: le constructeur auquel vous faites référence est défini pour la mise en œuvre HashMap d'un Map , (ainsi que pour les autres) mais pas pour l'interface Map elle-même (par exemple, considérons l'implémentation Fournisseur de l'interface Map: vous ne trouverez pas ce constructeur).

D'un autre côté, il n'est pas conseillé d'utiliser la méthode clone(), comme l'a expliqué Josh Bloch.

En ce qui concerne l'interface de la carte (et de votre question, dans laquelle vous demandez comment copier une carte, pas une carte de hachage), vous devez utiliser Map # putAll () :

Copie toutes les correspondances de la carte spécifiée vers cette carte (opération facultative). L'effet de cet appel est équivalent à celui de l'appel de put (k, v) sur cette carte une fois pour chaque mappage de la clé k à la valeur v dans la carte spécifiée.

Exemple:

// HashMap here, but it works for every implementation of the Map interface
Map<String, Object> data = new HashMap<String, Object>();
Map<String, Object> shallowCopy = new HashMap<String, Object>();

shallowCopy.putAll(data);
59
Luca Fagioli

Copier une carte sans connaître son implémentation:

static final Map shallowCopy(final Map source) throws Exception {
    final Map newMap = source.getClass().newInstance();
    newMap.putAll(source);
    return newMap;
}
11
Terris