Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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:

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?

like image 832
Michal Kordas Avatar asked Aug 06 '15 20:08

Michal Kordas


People also ask

How do I make a copy of an existing object?

To create a copy of an existing object in the vault, right-click the object of your choice and select Make Copy from the context menu. This command creates an entirely new object using the metadata and contents of the source object.


2 Answers

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 Properties for performance reasons unless you need it, because it inherits from 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.

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?


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 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.

like image 87
durron597 Avatar answered Oct 15 '22 23:10

durron597


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

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

like image 27
Pumphouse Avatar answered Oct 15 '22 22:10

Pumphouse