如何复制 java.util.Properties 对象?
How do I make a copy of java.util.Properties object?
我有以下字段和构造函数:
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 中有一些实用程序?
使用 putAll()
很棒...如果您需要继续使用 Properties
。它在 O(number of elements)
中运行并且开销很小。我建议的唯一区别是出于性能原因远离 Properties
除非你需要它,因为它继承自 Hashtable
. Also, don't use Properties
because it doesn't actually conform to any interface, just Dictionary
which is an abstract class; this will limit your options. See: What does it mean to "program to an interface"?
As of the Java 2 platform v1.2, this class was retrofitted to implement the Map
interface, making it a member of the Java Collections Framework. Unlike the new collection implementations, Hashtable
is synchronized. If a thread-safe implementation is not needed, it is recommended to use HashMap
in place of Hashtable
. If a thread-safe highly-concurrent implementation is desired, then it is recommended to use ConcurrentHashMap
in place of Hashtable.
无论你做什么,都不要使用 clone()
, 它既不安全也不高效。参见:
您编辑了问题以询问有关 Guava 和 apache-commons 的问题。如果是纯粹的防御副本,而且是不可变的,我会推荐使用Map<String, String> map = ImmutableMap.copyOf(properties)
. Note: again, this doesn't use an actual Properties
object because Hashtable
is not recommended unless you need it. From the wiki
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.
Properties 实现了 Cloneable,因此您可以根据需要执行以下操作。
this.properties = (Properties) properties.clone();
将此添加到您的 class
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
或者,如果您担心使用克隆,您的 class 也实现了可序列化,因此您可以这样做。
import org.apache.commons.lang.SerializationUtils;
this.properties = SerializationUtils.clone(properties);
或者您可以按 "long" 方式进行:
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));
}
试试这个:
Properties newProps = new Properties();
properties.forEach((key, value) -> {
newProps.setProperty((String) key, (String) value);
});
下面的程序将一个 属性 文件复制到另一个文件,并且还会删除重复项。源 属性 文件可能有重复的属性,但它会创建没有任何重复属性的新文件。
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();
}
}
}
另一种方法就是
Properties newVersion = new Properties(originalVersion);
它将表现为最初作为originalVersion
的副本,除非newVersion
中的键被删除,它将恢复为originalVersion
中存储的值。实际上,originalVersion
表现为默认的 key/value 集。
我有以下字段和构造函数:
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 中有一些实用程序?
使用 putAll()
很棒...如果您需要继续使用 Properties
。它在 O(number of elements)
中运行并且开销很小。我建议的唯一区别是出于性能原因远离 Properties
除非你需要它,因为它继承自 Hashtable
. Also, don't use Properties
because it doesn't actually conform to any interface, just Dictionary
which is an abstract class; this will limit your options. See: What does it mean to "program to an interface"?
As of the Java 2 platform v1.2, this class was retrofitted to implement the
Map
interface, making it a member of the Java Collections Framework. Unlike the new collection implementations,Hashtable
is synchronized. If a thread-safe implementation is not needed, it is recommended to useHashMap
in place ofHashtable
. If a thread-safe highly-concurrent implementation is desired, then it is recommended to useConcurrentHashMap
in place of Hashtable.
无论你做什么,都不要使用 clone()
, 它既不安全也不高效。参见:
您编辑了问题以询问有关 Guava 和 apache-commons 的问题。如果是纯粹的防御副本,而且是不可变的,我会推荐使用Map<String, String> map = ImmutableMap.copyOf(properties)
. Note: again, this doesn't use an actual Properties
object because Hashtable
is not recommended unless you need it. From the wiki
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.
Properties 实现了 Cloneable,因此您可以根据需要执行以下操作。
this.properties = (Properties) properties.clone();
将此添加到您的 class
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
或者,如果您担心使用克隆,您的 class 也实现了可序列化,因此您可以这样做。
import org.apache.commons.lang.SerializationUtils;
this.properties = SerializationUtils.clone(properties);
或者您可以按 "long" 方式进行:
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));
}
试试这个:
Properties newProps = new Properties();
properties.forEach((key, value) -> {
newProps.setProperty((String) key, (String) value);
});
下面的程序将一个 属性 文件复制到另一个文件,并且还会删除重复项。源 属性 文件可能有重复的属性,但它会创建没有任何重复属性的新文件。
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();
}
}
}
另一种方法就是
Properties newVersion = new Properties(originalVersion);
它将表现为最初作为originalVersion
的副本,除非newVersion
中的键被删除,它将恢复为originalVersion
中存储的值。实际上,originalVersion
表现为默认的 key/value 集。