2015-08-06 2 views
6

У меня есть следующие поля и конструктор:Как создать копию объекта java.util.Properties?

private final Properties properties; 

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

хорошая практика, чтобы сделать копию каждой изменяемой коллекции в конструкторе. Я хочу сделать мелкую независимую копию. Как я могу это достичь?

Моя первая идея состояла в том, чтобы использовать putAll() метод:

private final Properties properties = new Properties(); 

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

Есть ли более простой, более производительным и более идиоматических способ сделать это? Возможно, в Гуаве или Apache Commons есть некоторые утилиты?

ответ

5

Использование putAll() отлично ... если вам нужно остановиться с Properties. Он работает в O(number of elements) и имеет очень мало накладных расходов. Единственная разница, которую я бы рекомендовал, - держаться подальше от Properties по соображениям производительности, если вам это не нужно, потому что она наследует от Hashtable. Кроме того, не используйте Properties, потому что он фактически не соответствует ни одному интерфейсу, только Dictionary, который является абстрактным классом; это ограничит ваши варианты. См: What does it mean to "program to an interface"?

Как платформенный v1.2 Java 2, этот класс был модернизирован для реализации интерфейса Map, что делает его членом Framework Java Collections. В отличие от новых реализаций коллекции, синхронизируется Hashtable. Если поточно-безопасная реализация не требуется, рекомендуется использовать HashMap вместо Hashtable. Если требуется поточнобезопасная высококонкурентная реализация, тогда вместо Hashtable рекомендуется использовать ConcurrentHashMap.

Что бы вы ни делали, не использовать clone(), это не является безопасным и не производительным. См: Java: Why shouldn't clone() be used for defensive copying?


Вы изменили свой вопрос, чтобы спросить о гуавы и апача-достоянию. Если это чисто защитная копия, и она неизменна, я бы порекомендовал использовать Map<String, String> map = ImmutableMap.copyOf(properties). Примечание: опять же, это не использует фактический объект Properties, потому что Hashtable не рекомендуется, если это вам не нужно. От the wiki

Когда вы не ожидаете, чтобы изменить коллекцию, или ожидать, коллекция остается постоянной, это хорошая практика, чтобы защищаясь скопировать его в непреложные коллекции.

Важно. Каждая из реализаций неизменной коллекции Guava отклоняет нулевые значения. Мы провели исчерпывающее исследование внутренней базы данных кодов Google, в которой указывалось, что нулевые элементы разрешены в сборниках примерно в 5% случаев, а остальные 95% случаев лучше всего обслуживаются путем быстрого отказа от нулей. Если вам нужно использовать нулевые значения, подумайте об использовании Collections.unmodifiableList и его друзей в реализации коллекции, которая разрешает null. Более подробные предложения можно найти здесь.

+1

'this.properties = ImmutableMap.copyOf (свойства); '- это, к сожалению, не компилируется –

0

Свойства реализуются клонов, поэтому, если хотите, вы можете сделать следующее.

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

добавить это в класс

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

Или, если вы беспокоитесь об использовании клона, ваш класс также реализует сериализацию, так что вы могли бы сделать это.

import org.apache.commons.lang.SerializationUtils; 

this.properties = SerializationUtils.clone(properties); 

Properies

Cloneable

1

Или вы можете просто сделать это "длинный" путь:

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

итератора из того же java.util пакет как недвижимость, так что нет внешние зависимости.

Если компилятор предупреждает о непроверенных типов беспокоит вас, вы можете просто изменить его (предполагая, что ключи собственности являются строками):

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

Попробуйте это:

Properties newProps = new Properties(); 
properties.forEach((key, value) -> { 
    newProps.setProperty((String) key, (String) value); 
}); 
Смежные вопросы