web-dev-qa-db-fra.com

Comment puis-je copier un objet Java.util.Properties?

J'ai le champ et le constructeur suivants:

private final Properties properties;

public PropertiesExpander(Properties properties) {
    this.properties = properties;
}

La bonne pratique consiste à copier chaque collection mutable dans le constructeur. Je veux faire une copie peu profonde et indépendante. Comment puis-je y arriver?

Ma première idée était d'utiliser la méthode putAll():

private final Properties properties = new Properties();

public PropertiesExpander(Properties properties) {
    this.properties.putAll(properties);
}

Existe-t-il un moyen plus simple, plus performant ou plus idiomatique de le faire? Peut-être existe-t-il des outils pour cela dans Guava ou Apache Commons?

12
Michal Kordas

Utiliser putAll() est génial ... si vous devez rester avec Properties. Il fonctionne en O(number of elements) et a très peu de frais généraux. La seule différence que je recommanderais est de rester à l'écart de Properties pour des raisons de performance, sauf si vous en avez besoin, car il hérite de Hashtable . De même, n'utilisez pas Properties car il ne correspond à aucune interface, mais simplement Dictionary qui est une classe abstraite; cela limitera vos options. Voir: Que signifie "programmer pour une interface"?

À partir de la plate-forme Java 2 v1.2, cette classe a été modifiée pour implémenter l'interface Map, ce qui en fait un membre de Java Collections Framework. Contrairement aux nouvelles implémentations de la collection, Hashtable est synchronisé. Si une implémentation thread-safe n'est pas nécessaire, il est recommandé d'utiliser HashMap à la place de Hashtable. Si une implémentation hautement concurrente sécurisée pour les threads est souhaitée, il est recommandé d'utiliser ConcurrentHashMap à la place de Hashtable.

Quoi que vous fassiez, n'utilisez pas clone(), il n'est pas sécurisé et non performant. Voir: Java: Pourquoi clone () ne devrait-il pas être utilisé pour la copie défensive?


Vous avez modifié votre question pour poser des questions sur Guava et Apache-commons. Si c'est une copie purement défensive, et que c'est immuable , je recommanderais d'utiliser Map<String, String> map = ImmutableMap.copyOf(properties) . Remarque: encore une fois, cela n'utilise pas d'objet Properties réel car Hashtable n'est pas recommandé sauf si vous en avez besoin. De le wiki

Lorsque vous ne vous attendez pas à modifier une collection ou à attendre qu'une collection reste constante, il est recommandé de la copier de manière défensive dans une collection immuable.

Important: Chacune des implémentations de la collection immuable Guava rejette les valeurs NULL. Nous avons effectué une étude exhaustive de la base de code interne de Google, indiquant que les éléments nuls étaient autorisés dans les collections environ 5% du temps, et que les 95% restants étaient mieux servis en échouant rapidement sur les valeurs nuls. Si vous devez utiliser des valeurs null, envisagez d'utiliser Collections.unmodifiableList et ses amis pour une implémentation de collection qui autorise null. Des suggestions plus détaillées peuvent être trouvées ici.

9
durron597

Essaye ça:

Properties newProps = new Properties();
properties.forEach((key, value) -> {
    newProps.setProperty((String) key, (String) value);
});
2
Pavel Evstigneev

Ou vous pouvez simplement faire le "long" chemin:

    Iterator i = properties.keySet().iterator();
    while(i.hasNext()){
        this.properties.put(i.next(), properties.get(i));
    }

Iterator provient du même package Java.util que Properties, donc pas de dépendances extérieures.

Si l'avertissement du compilateur au sujet des types non vérifiés vous dérange, vous pouvez simplement le changer en (en supposant que vos clés de propriété sont des chaînes):

    Iterator<Object> i = properties.keySet().iterator();
    while(i.hasNext()){
        this.properties.put(i.next().toString(), properties.get(i));
    }
1
Scott Schechter

Properties implémente Cloneable, vous pouvez donc effectuer les opérations suivantes si vous le souhaitez.

this.properties = (Properties) properties.clone();

ajoutez ceci à votre classe

protected Object clone() throws CloneNotSupportedException {
    return super.clone();
}

Ou si vous êtes préoccupé par l'utilisation de clone, votre classe implémente également serializable, afin que vous puissiez le faire.

import org.Apache.commons.lang.SerializationUtils;

this.properties = SerializationUtils.clone(properties);

Propriétés

Clonable

0
Pumphouse