Working on a Java application and discovered that you need to convert a Properties object to a Map object?
If so, then your favorite search engine brought you to the right place. Cuz I'll show you how to do it here.
Just make sure you've got a recent version of Java (at least Java 8). If not, you'll need to keep searching.
Let's get started.
The Properties class inherits from Hashtable, another relative of Map.
Back in the day, a popular tech interview question for aspiring Java developers was: "What's the difference between Hashtable and HashMap?"
I always answered that the second word in Hashtable issn't capitalized but the second word in HashMap is. I never got the job. :(
(The correct answer is that Hashtable is synchronized whereas HashMap isn't.)
But Hashtable has gone the way of the dodo. I ain't seen anyone use it in years.
Anyway, the point of this whole section is this: the Properties object already looks strikingly similar to HashMap. It's a series of key/value pairs where both key and value are (almost always) String objects.
That makes your life easier when it comes to doing the conversion.
Stream of Consciousness
Probably the best way to handle the conversion process here is by following the lead of the cool kids and using a Stream object.
If you're unfamiliar with Stream, it's used to transform a collection of objects (such as in a List or a Set) to a sequence so that you can perform some operations on each object in the collection. It's often used for map-reduce tasks.
For the purposes of this guide, I'll use Stream to transform a Properties object into a Map object.
Let's say you're tracking users of your SaaS application and you've got a Properties object that associates the user's name with the user's level of service. Here's some testing code that reflects the requirement:
Properties properties = new Properties(); properties.put("Joe", "Premium"); properties.put("Jack", "Basic"); properties.put("John", "Premium");
Now suppose you need to transform that Properties object into a Map object. Here's the code that will do the trick:
Map<String, String> map = properties .entrySet() .stream() .collect( Collectors.toMap( e -> String.valueOf(e.getKey()), e -> String.valueOf(e.getValue()), (oldValue, newValue) -> oldValue, HashMap::new ));
There's a lot happening there so let me break it down.
First, the code grabs the entry set (with the entrySet() method) from the Properties object. That's going to return a Set of Entry objects.
Each Entry object represents a key/value pair.
Next, the code instantiates a Stream object from the Set.
After that, the code invokes the collect() method on the Stream object. That method is what the cool kids call a terminal operation because the pipeline is considered consumed once it finishes.
The collect() method is overloaded. The code above uses the version of the method that accepts a single parameter of a Collector type.
In this case, the Collector type creates a Map object thanks to the static toMap() method on the Collectors class.
That toMap() method accepts no fewer than four (4) parameters. Yeesh.
The first parameter is the key for the Map entry.
The second parameter is the value associated with that key.
The third parameter is a merge function that tells the application how to handle key conflicts. In this case, it takes the old value that it already found.
But it's not likely you'll have key conflicts when performing this conversion.
The fourth parameter instantiates a new HashMap object with a method reference.
If you'd like preserve insertion order, just make that HashMap::new into a LinkedHashMap::new and you're all set.
As I said above, collect() is a terminal operation so there's no more method chaining going on after that method.
Run that code and you'll get a Map that reflects the key/value pairs from your Properties object.
Wrapping It Up
Yes. It's that easy.
Now it's up to you to take the code you see above and copy and paste it into your own source. Then, massage it to suit your own requirements.
Photo by from