2010-01-05 99 views
50

我试图在我的课程中使用默认的java.util.Properties对象,并使用它接受的默认属性,并让开发人员通过指定另一个对象来覆盖其中的某些对象,但找不到一个好的方法。如何合并两个java.util.Properties对象?

的预期用途如下:

Properties defaultProperties = new Properties(); 
defaultProperties.put("key1", "value1"); 
defaultProperties.put("key2", "value2"); 

Properties otherProperties = new Properties(); 
otherProperties.put("key2", "value3"); 

Properties finalProperties = new Properties(defaultProperties); 

// 
// I'd expect to have something like: 
// 
// finalProperties.merge(otherProperties); 
// 
+0

有人回答,但删除了答案,指出正确的方法是使用'putAll()'方法,这是正确的答案,并达到我想要的。我没有注意到'java.util.Properties'扩展了'java.util.Hashtable'。 – Igor 2010-01-05 08:45:59

+0

你为什么认为我的回答不正确? – Jerome 2010-01-05 08:49:16

+1

这在技术上不是错误的,但我想要的是合并两个'java.util.Properties'文件而不迭代它的内容,这正是'putAll()'方法的作用。 – Igor 2010-01-05 08:52:11

回答

111

java.util.Properties实现java.util.Map接口,所以你可以只是把它当作这样,和使用方法,如putAll增加的另一个Map内容。

但是,如果你把它像一个地图,你必须非常小心这一点:

new Properties(defaultProperties); 

这往往捕捉人出来,因为它看起来像一个拷贝构造函数,但它不是”吨。如果使用该构造函数,然后调用类似keySet()(继承自其超类的Hashtable),则会得到一个空集,因为Map方法Properties不考虑传递给构造函数的默认Properties对象。如果您使用Properties本身中定义的方法(例如getPropertypropertyNames等),则仅识别默认值。

所以如果你需要合并两个属性的对象,它是安全做到这一点:

Properties merged = new Properties(); 
merged.putAll(properties1); 
merged.putAll(properties2); 

这会给你更多的可预见的结果,而不是随意标注其中一个作为“默认”属性设置。

通常情况下,我会从Java的早期建议不要治疗PropertiesMap,因为这是(在我看来)的执行错误(属性应该包含一个Hashtable,不延长它 - 这是懒惰的设计) ,但在Properties中定义的贫血界面本身并没有给我们许多选择。

+2

太棒了,但我仍然准备好写下你所描述的内容。你救了我一个错误。 – Igor 2010-01-05 08:54:25

+2

将Properties视为Map的另一个危险是它不是“Genericified”:'properties.put(“key”,new Object())'将被编译。 – Jerome 2010-01-05 09:35:28

+1

它会编译,是的,在某些情况下,它会正常工作,只要你使用'get()'重新得到它,并且不要尝试使用'getProperty()'来检索它。 – skaffman 2010-01-05 09:59:17

4

你快好:

Properties defaultProperties = new Properties(); 
defaultProperties.setProperty("key1", "value1"); 
defaultProperties.setProperty("key2", "value2"); 

Properties finalProperties = new Properties(defaultProperties); 
finalProperties.setProperty("key2", "value3"); 

编辑:通过setProperty取代put

1

是的,你是对的只是调用putAll方法,你就完成了。

+0

CW即使认为这是我刚刚给出的答案 – OscarRyz 2010-01-05 08:51:02

18

假设你最终想从文件中读取的属性,我会去在相同的属性加载这两个文件对象,如:

Properties properties = new Properties(); 
properties.load(getClass().getResourceAsStream("default.properties")); 
properties.load(getClass().getResourceAsStream("custom.properties")); 
1

的putAll(): 复制所有的映射,从指定的映射到这个散列表。这些映射将替换此散列表对当前指定映射中的任何键的任何映射。

Properties merged = new Properties(); 
merged.putAll(properties1); 
merged.putAll(properties2); 

第2行根本没有任何效果。第一个文件的任何属性都不在合并的属性对象中。

+1

**你的最后一行是完全不真实的**。属性1中不存在于属性2中的所有属性将通过设置为合并中的属性1中的值。 – 2014-11-20 16:37:10