如何制作java.util.Properties对象的副本?

时间:2015-08-06 20:00:11

标签: java collections properties copy copy-constructor

我有以下字段和构造函数:

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);
}

是否有更简单,更高效或更惯用的方法?也许在Guava或Apache Commons中有一些实用工具?

5 个答案:

答案 0 :(得分:13)

使用putAll()很棒......如果你需要留在Properties。它运行在O(number of elements)并且开销很小。我建议的唯一区别是出于性能原因远离Properties,除非您需要它,因为它继承自Hashtable。另外,不要使用Properties,因为它实际上并不符合任何接口,只是Dictionary这是一个抽象类;这将限制您的选择。请参阅:What does it mean to "program to an interface"?

  

从Java 2平台v1.2开始,该类被改进以实现Map接口,使其成为Java Collections Framework的成员。与新的集合实现不同,Hashtable是同步的。如果不需要线程安全实现,建议使用HashMap代替Hashtable。如果需要线程安全的高度并发实现,则建议使用ConcurrentHashMap代替Hashtable。

无论您做什么,都不要使用clone()它不安全且不具备效果。请参阅:Java: Why shouldn't clone() be used for defensive copying?

你编辑了你的问题,询问关于番石榴和apache-commons的问题。如果它纯粹是防御性副本,并且它是不可变的,我建议使用Map<String, String> map = ImmutableMap.copyOf(properties)。注意:同样,这不会使用实际的Properties对象,因为除非您需要Hashtable,否则不建议使用"test. 456. CREATED-BY-joe".partition("CREATED-BY-").last # => "joe" 。来自the wiki

  

当您不希望修改集合或期望集合保持不变时,将其防御性地复制到不可变集合中是一种很好的做法。

     

重要说明:每个Guava不可变集合实现都拒绝空值。我们对Google的内部代码库进行了详尽的研究,结果表明,大约5%的时间内,null元素在集合中被允许,而其他95%的情况最好是在空值上快速失败。如果需要使用空值,请考虑在允许null的集合实现上使用Collections.unmodifiableList及其朋友。更详细的建议可以在这里找到。

答案 1 :(得分:2)

属性实现Cloneable,因此如果您愿意,您可以执行以下操作。

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

将此添加到您的班级

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

或者如果你担心使用clone,你的类也实现了serializable,所以你可以这样做。

import org.apache.commons.lang.SerializationUtils;

this.properties = SerializationUtils.clone(properties);

Properies

Cloneable

答案 2 :(得分:2)

试试这个:

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

答案 3 :(得分:1)

或者你可以做到&#34; long&#34;方式:

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

Iterator来自与属性相同的java.util包,因此没有外部依赖项。

如果关于未经检查的类型的编译器警告困扰您,您可以简单地将其更改为(假设您的属性键是字符串):

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

答案 4 :(得分:0)

以下程序将一个属性文件复制到另一个属性文件,并且还将删除重复的文件。源属性文件可能具有重复的属性,但是它将创建没有任何重复属性的新文件。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.Set;

public class App2 {

    public static void main(String[] args) {

        try (InputStream input = new FileInputStream("config.properties")) {

            Properties prop = new Properties();

            // load a properties file
            prop.load(input);

            writeToNewProperties(prop);
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

    private static void writeToNewProperties(Properties prop) {
        Properties outPutProp = new Properties();
        // get the property value and print it out
        Set<String> stringPropertyNames = prop.stringPropertyNames();
        for (String propertyName : stringPropertyNames) {
            outPutProp.put(propertyName, prop.get(propertyName));
        }

        try (OutputStream output = new FileOutputStream("out-config.properties")) {
            // save properties to project root folder
            outPutProp.store(output, null);
            System.out.println(outPutProp);
        } catch (IOException io) {
            io.printStackTrace();
        }
    }

}