How to create a copy of java.util.Properties object?

I have the following field and constructor:

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

It is good practice to copy each mutable collection in the constructor. I want to make a shallow independent copy. How can i achieve this?

My first idea was to use the putAll() method:

 private final Properties properties = new Properties(); public PropertiesExpander(Properties properties) { this.properties.putAll(properties); } 

Is there an easier, more advanced, or more idiomatic way to do this? Maybe there are some utilities for this in Guava or Apache Commons?

+16
source share
5 answers

Using putAll() great ... if you need to stay in Properties . It works in O(number of elements) and has very little overhead. The only difference I would recommend is to stay away from Properties for performance reasons if you don't need it because it inherits from Hashtable . Also, do not use Properties because it does not actually correspond to any interface, just a Dictionary which is an abstract class; it will limit your possibilities. See: what does "programming for an interface" mean?

Starting with the Java 2 v1.2 platform, this class has been modified to implement the Map interface, which made it a member of the Java Collections Framework. Unlike new collection implementations, the Hashtable synchronized. If a thread-oriented implementation is not required, it is recommended that you use a HashMap instead of a Hashtable . If a highly competitive multi-threaded implementation is required, then it is recommended to use ConcurrentHashMap instead of Hashtable.

Whatever you do, do not use clone() , it is unsafe and does not work. See: Java: Why can't you use clone () for secure copy?


You edited your question to ask about guava and apache-commons. If this is a purely protective copy and it is immutable , I would recommend using Map<String, String> map = ImmutableMap.copyOf(properties) . Note: again, the actual Properties object is not used here because a Hashtable not recommended if you do not need it. From wiki

If you do not expect to change the collection or expect the collection to remain constant, we recommend that you securely copy it to an immutable collection.

Important Note: Each of the implementations of the immutable Guava collection rejects null values. We conducted a comprehensive study of the internal Google code base, which showed that null items were allowed in collections in about 5% of cases, and the remaining 95% of cases were best served by quickly rejecting null values. If you need to use null values, consider using Collections.unmodifiableList and his friends to implement a collection that allows a null value. More detailed offers can be found here.

+13
source

Properties implement Cloneable, so if you want, you can do the following.

 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 a clone, your class also implements serializable, so you can do it.

 import org.apache.commons.lang.SerializationUtils; this.properties = SerializationUtils.clone(properties); 

Ownership

Cloneable

+2
source

Try the following:

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

Or you can just do it in a "long" way:

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

An iterator from the same java.util package as properties, so no external dependencies.

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

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

The program below copies one property file to another and also deletes duplicates. The source properties file may have duplicate properties, but it will create a new file without 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(); } } } 
0
source

All Articles