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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31864727/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 19:16:05  来源:igfitidea点击:

How do I make a copy of java.util.Properties object?

javacollectionspropertiescopycopy-constructor

提问by Michal Kordas

I have the following field and constructor:

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

private final Properties properties;

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

The good practice is to make copy of every mutable collection in constructor. I want to make a shallow, independent copy. How can I achieve that?

好的做法是在构造函数中复制每个可变集合。我想做一个浅薄的、独立的副本。我怎样才能做到这一点?

My first idea was to use putAll()method:

我的第一个想法是使用putAll()方法:

private final Properties properties = new Properties();

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

Is there any simpler, more performant or more idiomatic way of doing that? Maybe there are some utils for that in Guava or Apache Commons?

有没有更简单、更高效或更惯用的方法来做到这一点?也许在 Guava 或 Apache Commons 中有一些实用程序?

采纳答案by durron597

Using putAll()is great... if you need to stay with Properties. It runs in O(number of elements)and has very little overhead. The only difference I would recommend is to stay away from Propertiesfor performance reasons unless you need it, because it inherits from Hashtable. Also, don't use Propertiesbecause it doesn't actually conform to any interface, just Dictionarywhich is an abstract class; this will limit your options. See: What does it mean to "program to an interface"?

使用putAll()很棒……如果您需要继续使用Properties. 它运行O(number of elements)并具有很少的开销。我建议的唯一区别是Properties出于性能原因远离它,除非您需要它,因为它继承自Hashtable. 另外,不要使用,Properties因为它实际上不符合任何接口,只是Dictionary一个抽象类;这将限制您的选择。请参阅:“编程到接口”是什么意思?

As of the Java 2 platform v1.2, this class was retrofitted to implement the Mapinterface, making it a member of the Java Collections Framework. Unlike the new collection implementations, Hashtableis synchronized. If a thread-safe implementation is not needed, it is recommended to use HashMapin place of Hashtable. If a thread-safe highly-concurrent implementation is desired, then it is recommended to use ConcurrentHashMapin place of Hashtable.

从 Java 2 平台 v1.2 开始,该类经过改造以实现该Map接口,使其成为 Java 集合框架的成员。与新的集合实现不同,Hashtable是同步的。如果不需要线程安全的实现,建议使用HashMap到位Hashtable。如果需要线程安全的高并发实现,那么建议使用ConcurrentHashMapHashtable 代替。

Whatever you do, do not use clone(),it is not secure and not performant. See: Java: Why shouldn't clone() be used for defensive copying?

无论您做什么,都不要使用clone()它不安全且性能不佳。请参阅:Java:为什么不应该将 clone() 用于防御性复制?



You edited your question to ask about Guava and apache-commons. If it's purely a defensive copy, and it's immutable, I would recommend using Map<String, String> map = ImmutableMap.copyOf(properties). Note: again, this doesn't use an actual Propertiesobject because Hashtableis not recommended unless you need it. From the wiki

您编辑了您的问题以询问 Guava 和 apache-commons。如果它纯粹是一个防御性副本,并且它是不可变的,我会建议使用Map<String, String> map = ImmutableMap.copyOf(properties). 注意:同样,这不使用实际Properties对象,因为Hashtable除非您需要,否则不推荐使用。来自维基

When you don't expect to modify a collection, or expect a collection to remain constant, it's a good practice to defensively copy it into an immutable collection.

Important: Each of the Guava immutable collection implementations rejects null values. We did an exhaustive study on Google's internal code base that indicated that null elements were allowed in collections about 5% of the time, and the other 95% of cases were best served by failing fast on nulls. If you need to use null values, consider using Collections.unmodifiableList and its friends on a collection implementation that permits null. More detailed suggestions can be found here.

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

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

回答by Pavel Evstigneev

Try this:

试试这个:

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

回答by Pumphouse

Properties implements Cloneable, so it looks like you could do the following if you wanted.

Properties 实现了 Cloneable,因此看起来您可以根据需要执行以下操作。

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

add this to your class

将此添加到您的课程中

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

Or if you're worried about using clone, your class also implements serializable, so you could do this.

或者,如果您担心使用克隆,您的类也实现了可序列化,因此您可以这样做。

import org.apache.commons.lang.SerializationUtils;

this.properties = SerializationUtils.clone(properties);

Properies

属性

Cloneable

可克隆

回答by Scott Schechter

Or you can just do it the "long" way:

或者你可以用“长”的方式来做:

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

Iterator is from the same java.util package as Properties, so no outside dependencies.

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

If the compiler warning about unchecked types bothers you, you can simply change it to (assuming your property keys are strings):

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

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

回答by Sudhakar

The below program copies the one property file to another and will remove the duplicates also. The source property file may have duplicate properties but it will create the new file without any duplicate properties.

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

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

}