Converting Map<String,String> to Map<String,Object> - java

I have Two Maps
Map<String, String> filterMap
Map<String, Object> filterMapObj
What I need is I would like to convert that Map<String, String> to Map<String, Object>.
Here I am using the code
if (filterMap != null) {
for (Entry<String, String> entry : filterMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
Object objectVal = (Object)value;
filterMapObj.put(key, objectVal);
}
}
It works fine, Is there any other ways by which I can do this without iterating through all the entries in the Map.

Instead of writing your own loop that calls put, you can putAll, which does the same thing:
filterMapObj.putAll(filterMap);
(See the Javadoc.)
And as Asanka Siriwardena points out in his/her answer, if your plan is to populate filterMapObj immediately after creating it, then you can use the constructor that does that automatically:
filterMapObj = new HashMap<>(filterMap);
But to be clear, the above are more-or-less equivalent to iterating over the map's elements: it will make your code cleaner, but if your reason for not wanting to iterate over the elements is actually a performance concern (e.g., if your map is enormous), then it's not likely to help you. Another possibility is to write:
filterMapObj = Collections.<String, Object>unmodifiableMap(filterMap);
which creates an unmodifiable "view" of filterMap. That's more restrictive, of course, in that it won't let you modify filterMapObj and filterMap independently. (filterMapObj can't be modified, and any modifications to filterMap will affect filterMapObj as well.)

You can use the wildcard operator for this.
Define filterMapObj as Map<String, ? extends Object> filterMapObj and you can directly assign the filterMap to it. You can learn about generics wildcard operator

You can simply write
Map<String, Object> filterMapObj = new HashMap<>(filterMap);

You can use putAll method to solve the problem.The Object is the father class of all objects,so you can use putAll without convert.

Related

How can I combine two HashMap objects containing the different types?

I have two HashMap objects defined as:
Map<String, String> requestParams = new HashMap<>();
Map<String, Boolean> requestParamForOauth = new HashMap<>();
How can I merge these two maps?
Assuming that both maps contain the same set of keys, and that you want to "combine" the values, the thing you would be looking for is a Pair class, see here for example.
You simply iterate one of the maps; and retrieve values from both maps; and create a Pair; and push that in your result map.
The only downside is that there is no "official" Pair class that you could use (see here for more thoughts around that).
Alternatively, if there is a "deeper" meaning of those "combined" values (beyond a simple "tuple/pair" semantics), you could instead create your own class that wraps around those two values.
Your keys are of the same type (String), but the values are not even related by an interface or super class, you will need to define a Map<String, Object> and make use of the Map#putAll method
Map<String, String> requestParams = new HashMap<>();
Map<String, Boolean> requestParamForOauth = new HashMap<>();
Map<String, Object> requestParamForOauth2 = new HashMap<>();
requestParamForOauth2.putAll(requestParams);
requestParamForOauth2.putAll(requestParamForOauth);
If you want to use one list to store all the data You can
use one HashMap<String,Object>
What do you want to do when the same key appears in both Map? If you want to keep both the String and Boolean, then you'll need a map that looks like this: Map<String, Pair(String, Boolean)>. If you just want to keep one value, then Map<String, Object> is what you want.

Best way to map keys of a Map

I want to transform keys in a HashMap. The map has lower_underscore keys but an expected map should have camelCase keys. The map may also have null values.
The straightfoward code to do this is here:
Map<String, Object> a = new HashMap<String, Object>() {{
put("foo_bar", 100);
put("fuga_foga", null); // A value may be null. Collectors.toMap can't handle this value.
}};
Map<String, Object> b = new HashMap<>();
a.forEach((k,v) -> b.put(toCamel(k), v));
I want to know the method to do this like Guava's Maps.transformValues() or Maps.transformEntries(), but these methods just transforms values.
Collectors.toMap() is also close, but this method throws NullPointerException when a null value exists.
Map<String, Object> collect = a.entrySet().stream().collect(
Collectors.toMap(x -> toCamel(x.getKey()), Map.Entry::getValue));
If you absolutely want to solve this using streams, you could do it like this:
Map<String, Object> b = a.entrySet()
.stream()
.collect(HashMap::new,
(m, e) -> m.put(toCamel(e.getKey()), e.getValue()),
HashMap::putAll);
But I find the "conventional" way shown in your question easier to read:
Map<String, Object> b = new HashMap<>();
a.forEach((k,v) -> b.put(toCamel(k), v));
This is intended as a comment, but got too long for that.
Wanting something like Guava's Maps.transformValues() or Maps.transformEntries() doesn't make too much sense I think.
Those methods return a view of the original map and when you get some
value using a key then the value is transformed by some function that you specified.
(I could be wrong here because I'm not familiar with Guava but I'm making these assumptions based on documentation)
If you wanted to do "transform" the keys then you could do it by writing a wapper for the map like so:
public class KeyTransformingMap<K, V> implements Map {
private Map<K, V> original;
private Function<K, K> reverseTransformer;
public V get(Object transformedKey) {
K originalKey = reverseTransformer.apply((K) transformedKey);
return original.get(originalKey);
}
// delegate all other Map methods directly to original map (or throw UnsupportedOperationException)
}
In your case where you have a map with snake case keys but want camel case keys,
the reverseTransformer function would take in a camel case string and return a snake case string.
I.e reverseTransformer.apply("snakeCase") returns "snake_case" which you can then use as a key for the original map.
Having said all that I think that the straightforward code you suggested is the best option.

Is it possible to return a HashMap object in Java?

I have a method that maps keywords to a certain value. I want to return the actual hashmap so I can reference its key/value pairs
Yes. It is easily possible, just like returning any other object:
public Map<String, String> mapTheThings(String keyWord, String certainValue)
{
Map<String, String> theThings = new HashMap<>();
//do things to get the Map built
theThings.put(keyWord, certainValue); //or something similar
return theThings;
}
Elsewhere,
Map<String, String> actualHashMap = mapTheThings("keyWord", "certainValue");
String value = actualHashMap.get("keyWord"); //The map has this entry in it that you 'put' into it inside of the other method.
Note, you should prefer to make the return type Map instead of HashMap, as I did above, because it's considered a best practice to always program to an interface rather than a concrete class. Who's to say that in the future you aren't going to want a TreeMap or something else entirely?

java clone a map which contains a nested map

I have this code:
Map<String, Map<String,String>> map = new HashMap<String, Map<String,String>> ();
I wanna clone this map, I did like this:
Map<String, Map<String, String>> newMap = (Map<String, Map<String, String>>) ((HashMap<String, Map<String,String>>) map).clone();
Then:
System.out.println(map.get("myKey1").get("myKey2"));
newMap.get("myKey1").put("myKey2","testValue");
System.out.println(map.get("myKey1").get("myKey2"));
System.out.println(newMap.get("myKey1").get("myKey2"));
I get this output:
map.get("myKey1").get("myKey2"): OldValue
map.get("myKey1").get("myKey2"): testValue
newMap.get("myKey1").get("myKey2"): testValue
It's strange when getting map.get("myKey1").get("myKey2") = testValue !
https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#clone()
Returns a shallow copy of this HashMap instance: the keys and values
themselves are not cloned.
ANSWER: You must iterate through any type of collection you want to copy and clone individual elements.
SUGGESTION: Java doesn't support cloning of objects by itself if you want to create some kind of automation consider using serialization.
http://www.avajava.com/tutorials/lessons/how-do-i-perform-a-deep-clone-using-serializable.html
This type of copying is called deep cloning.
By default in Java, the .clone() method doesn't actually make a "deep copy" of the object that you call it on. It's just going to give you a new reference variable and the object references in your new map are going to be copies of the references in your original map.
It's rather annoying, but if you need to clone certain objects in Java that haven't made a proper clone method, you need to just iterate through the object's data and place it into a new one (and make deep copies of objects where necessary).
So in your case, you can write loops that iterate through your map and make new references to new objects to be placed in your new map.
As a solution, I did like this:
Map<String,Map<String,String>> newMap = new HashMap<String, Map<String,String>>();
for (Entry<String, Map<String, String>> entry : map.entrySet()) {
newMap.put(entry.getKey(), (Map<String, String>) ((HashMap<String, String>) map.get(entry.getKey())).clone());
}

Casting a HashMap

i´m trying to make a casting of Hasmap
I have this hasmap:
Map<String, Object> requestargs = new Map<String, Object>();
Other side i have a method who bring me a hashmap of: Map<String, Document>
MultipartForm form = MgnlContext.getWebContext().getPostedForm();
The method is getDocuments();
I need to put the return of this method in my hashmap making something like this:
requestargs = form.getDocuments();
But i don´t know how to cast this Hasmap og (String,Document) to (String,Object)
Thanks
Unless you can use a wildcard
Map<String, ? extends Object> requestargs
You will need to copy the map into a new map:
requestargs = new HashMap<String, Object>(form.getDocuments());
The two types are not related directly. Were you able to make the assignment directly (or via casting) it would be possible to insert a value with non-Document type into the map, and that would be type-unsafe:
Map<String, Document> docs = form.getDocuments();
Map<String, Object> requestargs = docs; // not actually allowed
requestargs.put("Foo", new Object());
for (Document doc : docs.values()) {
// doc isn't necessarily a Document! ClassCastExceptions abound.
}
To prevent this problem happening, such an assignment is forbidden by the type system.
The wildcard works because it makes it impossible to call put on the map, since there is no way to know what types can be put into the map safely.

Categories