2015-08-06 10 views
6

Ho la seguente campo e costruttore:Come posso creare una copia dell'oggetto java.util.Properties?

private final Properties properties; 

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

La buona pratica è quella di effettuare una copia di ogni collezione mutabile nel costruttore. Voglio fare una copia superficiale e indipendente. Come posso ottenerlo?

La mia prima idea era quella di utilizzare il metodo putAll():

private final Properties properties = new Properties(); 

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

C'è un modo più semplice, più performante o più idiomatica di farlo? Forse ci sono alcuni strumenti per questo in Guava o Apache Commons?

risposta

5

Utilizzare putAll() è fantastico ... se è necessario stare con Properties. Funziona in O(number of elements) e ha un sovraccarico molto piccolo. L'unica differenza che vorrei raccomandare è di stare lontano da Properties per motivi di prestazioni a meno che non ne abbiate bisogno, perché eredita da Hashtable. Inoltre, non utilizzare Properties perché in realtà non è conforme a nessuna interfaccia, solo Dictionary che è una classe astratta; questo limiterà le tue opzioni. Vedere: What does it mean to "program to an interface"?

Come della piattaforma Java 2 v1.2, questa classe è stata retrofit per implementare l'interfaccia Map, rendendolo un membro del framework Java collezioni. A differenza delle nuove implementazioni di raccolta, Hashtable è sincronizzato. Se non è necessaria un'implementazione thread-safe, si consiglia di utilizzare HashMap al posto di Hashtable. Se si desidera un'implementazione altamente concomitante thread-safe, si consiglia di utilizzare ConcurrentHashMap al posto di Hashtable.

Qualunque cosa tu faccia, non utilizzare clone(), non è sicuro e non performante. Vedere: Java: Why shouldn't clone() be used for defensive copying?


Hai modificato la tua domanda per chiedere di Guava e apache-commons. Se si tratta di una copia puramente difensiva, ed è immutabile, ti consigliamo di utilizzare Map<String, String> map = ImmutableMap.copyOf(properties). Nota: di nuovo, questo non usa un oggetto effettivo Properties perché Hashtable non è raccomandato a meno che non ne abbiate bisogno. Da the wiki

Quando non si prevede di modificare una raccolta, o si aspetta una raccolta di rimanere costante, è una buona pratica per copiare sulla difensiva in una collezione immutabile.

Importante: ciascuna delle implementazioni di raccolta immutabili Guava rifiuta i valori nulli. Abbiamo condotto uno studio esaustivo sul codice interno di Google che indicava che gli elementi nulli erano consentiti nelle raccolte circa il 5% delle volte e che l'altro 95% dei casi era il migliore servito dal fallimento dei valori nulli. Se è necessario utilizzare valori nulli, prendere in considerazione l'uso di Collections.unmodifiableList e dei relativi amici su un'implementazione di raccolta che consente il null. Suggerimenti più dettagliati possono essere trovati qui.

+1

'this.properties = ImmutableMap.copyOf (proprietà); '- questo purtroppo non viene compilato –

0

Proprietà strumenti Clonabile, quindi sembra che si potrebbe fare quanto segue se lo si desidera.

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

aggiungere questo alla classe

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

Oppure, se siete preoccupati per utilizzando clone, la classe implementa anche serializzabile, in modo che si possa fare questo.

import org.apache.commons.lang.SerializationUtils; 

this.properties = SerializationUtils.clone(properties); 

Properies

Cloneable

1

Oppure si può semplicemente farlo nel modo "lungo":

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

Iterator è dello stesso package java.util come proprietà, in modo che nessun dipendenze esterne.

Se il compilatore di avviso sui tipi incontrollati ti dà fastidio, si può semplicemente cambiare a (assumendo le chiavi di proprietà sono stringhe):

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

Prova questa:

Properties newProps = new Properties(); 
properties.forEach((key, value) -> { 
    newProps.setProperty((String) key, (String) value); 
}); 
Problemi correlati