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?
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'utiliserHashMap
à la place deHashtable
. Si une implémentation hautement concurrente sécurisée pour les threads est souhaitée, il est recommandé d'utiliserConcurrentHashMap
à 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.
Essaye ça:
Properties newProps = new Properties();
properties.forEach((key, value) -> {
newProps.setProperty((String) key, (String) value);
});
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));
}
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);