How can I pass in a new HashMap in the most canonical (simplest, shortest hand) form?
// 1. ? (of course this doesn't work)
passMyHashMap(new HashMap<String, String>().put("key", "val"));
// 2. ? (of course this doesn't work)
passMyHashMap(new HashMap<String, String>(){"key", "val"});
void passMyHashMap(HashMap<?, ?> hm) {
// do stuff witih my hashMap
}
Create it, initialize it, then pass it:
Map<String,String> myMap = new HashMap<String,String>();
myMap.put("key", "val");
passMyHashMap(myMap);
You could use the "double curly" style that David Wallace mentions in a comment, I suppose:
passMyHashMap(new HashMap<String,String>(){{
put("x", "y");
put("a", "b");
}});
This essentially derives a new class from HashMap and sets up values in the initializer block. I don't particularly care for it (hence originally not mentioning it), but it doesn't really cause any problems per se, it's more of a style preference (it does spit out an extra .class file, although in most cases that's not a big deal). You could compress it all to one line if you'd like, but readability will suffer.
You can't call put and pass the HashMap into the method at the same time, because the put method doesn't return the HashMap. It returns the old value from the old mapping, if it existed.
You must create the map, populate it separately, then pass it in. It's more readable that way anyway.
HashMap<String, String> map = new HashMap<>();
map.put("key", "val");
passMyHashMap(map);
HashMap< K,V>.put
public **V** put(K key,V value)
Associates the specified value with the specified key in this map. If
the map previously contained a mapping for the key, the old value is
replaced.
Returns the previous value associated with key, or null if there was
no mapping for key. (A null return can also indicate that the map
previously associated null with key.)
As you can see, it does not return the type HashMap<?, ?>
You can't do that. What you can do is create a factory that allow you to do so.
public class MapFactory{
public static Map<String, String> put(final Map<String, String> map, final String key, final String valeu){
map.put(key, value);
return map;
}
}
passMyHashMap(MapFactory.put(new HashMap<String, String>(),"key", "value"));
Although I can't image a approach that would need such implementation, also I kinda don't like it. I would recommend you to create your map, pass the values and just then send to your method.
Map<String, String> map = new HashMap<String, String>();
map.put("key","value");
passMyHashMap(map);
Related
I need to convert raw Map to Map<string,string>, and I think I have to first convert the raw map to Map<Object,Object> and then convert it again to Map<String,String>.
code snippet goes like below.
Map obj1 = new HashMap();
obj1.put("key1", 1);
obj1.put("key2", false);
obj1.put("key3", 3.94f);
Map<Object, Object> obj2 = obj1;
Map<String, String> obj = new HashMap<String,String>();
for (Map.Entry<Object, Object> entry: obj2.entrySet()) {
obj.put(entry.getKey().toString(), entry.getValue().toString());
}
I guess it would work in any condition but I want to hear from others about possible danger of this code.(any possiblities for ClassCastException for example?)
Please also let me know if you have a better idea.
-- revised code
Map obj1 = new HashMap();
obj1.put(2, 1);
obj1.put(true, false);
obj1.put(4.4f, 3.94f);
Map<String, String> obj = new HashMap<String,String>();
for (Object k : obj1.keySet()){
obj.put(k.toString(), obj1.get(k).toString());
}
Since raw Map entries will contain key/value of Objects anyway, I think I don't need temporary Map<Object,Object>. Just iterating over each item works well and I don't see any issues so far.
If You Look out the Definition of HashMap in jdk 1.4 It was earlier Implements using Object Class when generics Concept not came.
When generics is Introduced this object is Replaced with <T>. But If you Still don't use Generics Type Safe then Internally this Statement new HashMap() reflects a instance of <Object, Object>. Better To use directly a
a new HashMap() is better idea. There should no need of Map <Object, Object> obj2.
So, GO For this.. a better approach.
Map obj1 = new HashMap();
obj1.put("key1", 1);
obj1.put("key2", false);
obj1.put("key3", 3.94f);
Map<Object, Object> obj2 = obj1;
Map<String, String> obj = new HashMap<String,String>();
for (Object obj_Entry : obj1.entrySet()) {
Map.Entry entry = (Map.Entry) obj_Entry; // This will Work Fine all Time.
obj.put(entry.getKey().toString(), entry.getValue().toString());
}
Your code will not generate ClassCastExceptions. Actually you are not doing any casting here. You just call the toString() method of every key/value pair to make it a string. As long as toString() returns a valid value of your objects. Your code will be fine.
But your code may produce NullPointerExceptions if your obj1 contain null keys or objects
obj1.put(null, "null value")
Also note that some key collisions may occur if toString() methods return same String value for two keys. This is unlikely but it is possible.
Is it possible for a Hashmap to keep its original key/value pair when a duplicate key is entered?
For example, let's say I have something like this:
Map<String, String> map = new HashMap<String, String>();
map.put("username","password1");
map.put("username","password2");
I want the original key/value pair - username, password1 to be kept and not be overrode by username, password2.
Is this possible? If not, how can I eliminate duplicate entries from being put into the map?
As mentioned, you can use putIfAbsent if you use Java 8.
If you are on an older Java version you can use a ConcurrentHashMap instead, which has a putIfAbsent method.
Of course, you get the additional overhead of thread safety, but if you are not writing an extremely performance sensitive application it should not be a concern.
If not on Java 8, you have some options.
The most straightforward is the verbose code everywhere
Object existingValue = map.get(key);
if(existingValue == null){
map.put(key,newValue);
}
You could have a utility method to do this for you
public <T,V> void addToMapIfAbsent(Map<T,V> map, T key, V value){
V oldValue = map.get(key);
if(oldValue == null){
map.put(key,value);
}
}
Or extend a flavor of Map and add it there.
public class MyMap<T,V> extends HashMap<T,V>{
public void putIfNotExist(T key, V value){
V oldValue = get(key);
if(oldValue == null){
put(key,value);
}
}
}
Which allows you to create a Map thusly
Map<String,String> map = new MyMap<>();
EDIT: Although, to get to the MyMap method, of course, you'll need to have the map variable declared as that type. So anywhere you need that, you'll have to take an instance of MyMap instead of Map.
https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html#putIfAbsent-K-V-
If you are using Java 8, you can use putIfAbsent.
I have been facing a question frequently regarding Hashtable.
How to convert key as value and value as key with out any data loss using java.util.Hashtable.
Hashtable ht = new Hashtable();
ht.put(1,"One");
ht.put(2,"Two");
ht.put(3,"One");
I would like to convert keys as "One","Two","One" and values as 1,2,3 respectively.
Thanks for your valuable support.
Here's a generic implementation that iterates over the entry set:
public static <K, V> Hashtable<V, K> reverseEntries(Hashtable<K, V> in) {
Hashtable<V, K> out = new Hashtable<V, K>();
for (Map.Entry<K, V> entry : in.entrySet())
out.put(entry.getValue(), entry.getKey());
return out;
}
Iterating over the entry set is the most efficient way to iterate over all entries because you get the key and value together (iterating over keys means you have to look up the entry for every key).
try this
public static void main(String[] args) {
Hashtable<Object, Object> ht1 = new Hashtable<Object, Object>();
ht1.put(1, "One");
ht1.put(2, "Two");
ht1.put(3, "One");
Hashtable<Object, Object> ht2 = new Hashtable<Object, Object>();
for (Object key : ht1.keySet())
{
Object value = ht1.get(key);
ht2.put(new Temp(value.toString()), key);
}
ht1.clear();
ht1.putAll(ht2);
}
EDIT
class Temp
{
String str1;
public Temp(String str1) {
this.str1 = str1;
}
}
by providing reference type that is object of class Temp you can avoid data loss.
The safest way to do this (by which I mean avoiding the situation where there is already a key that is equal to one of the values in the Hashtable as in your example with the value "one") is to copy to a new Hashtable, something like this:
Map copy = new Hashtable();
for (Map.Entry entry : original.entrySet())
{
copy.put(entry.getValue(), entry.getKey());
}
Then if you really need to get the keys and values back in the original, just do:
original.clear();
original.putAll(copy);
Google Guava has the BiMap interface with HashBiMap as an implementation:
BiMap<Integer,String> map = new HashBiMap<Integer,String>();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "One");
However, this "preserves the uniqueness of its values as well as that of its keys" (it is backed by two HashMaps), so in your particular case it wouldn't work, as two values are "One".
If you need this functionality then using Guava is probably the best way to approach it, but if you would rather understand how to implement this then looking at the source code of HashBiMap may also help.
I would like to convert keys as "One","Two","One" and values as 1,2,3 respectively
This is simply impossible. A Hashtable only stores one value for each key.
I have two Map of LinkedHashMap in this format==> Map<String,LinkedHashMap<String,String>> both m1 & m2 have same key values, How we combine this m1 & m2 and make m3 with all elements.
Note :Can you some one give psuedocode I will implement it.Thanks.
Input is like below format:
m1={1={rollno=1,name=chris,height=7ft},2={rollno=2,name=stephen,height=6ft}}
m2={1={rollno=1,name=chris,weight=65},2={rollno=2,name=stephen,weight=73}}
Output :
m3={1={rollno=1,name=chris,height=7ft,weight=65},2={rollno=2,name=stephen,height=6ft,weight=73}}
What I tried :
private static Map<String, LinkedHashMap<String, String>> mergeMap(Map<String,LinkedHashMap<String, String>> m1, Map<String, LinkedHashMap<String, String>> m2) {
Map<String,LinkedHashMap<String, String>> newMap = new LinkedHashMap<String, LinkedHashMap<String, String>>(m1);
for (Map.Entry<String, LinkedHashMap<String, String>> entry : m2.entrySet()) {
LinkedHashMap<String, String> t1=newMap.get(entry.getKey());
newMap.putAll(m2);
}
System.out.println("ouput :"+newMap);
return newMap;
}
You can follow the steps below to merge the maps:
First create a newMap, passing first map - map1 as parameter. You have to use the overloaded constructor - LinkedHashMap(Map) for that. Now you have a map with all the elements of map1. Half of your job is done.
Map<String, Map<String, String>> newMap = new LinkedHashMap<>(map1);
Then you need to move elements from 2nd map to the newMap. For that, you would need to iterate over map2. You can use Map#entrySet() method to iterate over each entry in map2. You would then use Map.Entry#getKey() and Map.Entry#getValue() methods to get the key and value respectively for each entry.
For each key in map2, get the current value from newMap, and merge the value of map2, with the value in newMap. Both the values are Map. You can use Map#putAll() method to merge the two maps. It will automatically ignore the already available keys, and add the extra key-value pair.
Now, after resolving the above issue, you should consider changing your data structure. You should create a class say Person, to store all those attributes, and maintain a Map<Integer, Person>, where key will be rollNo.
What you have shown is just what you have. If you could explain some other details like, how and from where did you get those maps, and why would you possibly have the attributes of same person distributed in two different maps, may be we can help you better to formulate the data structure properly. Having a nested Map might be handled if you have small set of data, but if you have larger set of data, you will face difficult in handling them. You should certainly follow Object Oriented Approach.
You should use java object to store complete information.
like
class Student{
int rollNo;
String name;
String height;
String weight;
}
And store your elements like
Map<Integer,Student> map = new HashMap<Integer,Student>();
it will be much easy to merge and store and manage element like this
I need a dictionary-like data structure that stores information as follows:
key [value 1] [value 2] ...
I need to be able to look up a given value by supplying the key and the value I desire (the number of values is constant). A hash table is the first thing that came to my mind but I don't think it can be used for multiple values. Is there any way to do this with a single datastrucuture rather than splitting each key-value pair into a separate list (or hash table)? Also I'd rather not use a multi-dimensional array as the number of entries is not known in advance. Thanks
I'm not sure what you mean about your list of values, and looking up a given value. Is this basically a keyed list of name-value pairs? Or do you want to specify the values by index?
If the latter, you could use a HashMap which contains ArrayLists - I'm assuming these values are String, and if the key was also a String, it would look something like this:
HashMap<String, ArrayList<String>> hkansDictionary = new HashMap<String, ArrayList<String>>();
public String getValue (String key, int valueIdx) {
ArrayList<String> valueSet = hkansDictionary.get(key);
return valueSet.get(valueIdx);
}
If the former, you could use a HashMap which contains HashMaps. That would look more like this:
HashMap<String, HashMap<String, String>> hkansDictionary
= new HashMap<String, HashMap<String, String>>();
----
public String getValue (String key, String name) {
HashMap<String, String> valueSet = hkansDictionary.get(key);
return valueSet.get(name);
}
You could make a class that holds the two key values you want to look up, implement equals() and hashcode() to check/combine calls to the underlying values, and use this new class as the key to your Map.
I would use
Map<Key,ArrayList<String>> map = new HashMap<Key,ArrayList<String>>
where you define Key as
public class Key{
private String key;
private String value;
//getters,setters,constructor
//implement equals and hashcode and tostring
}
then you can do
Key myKey = new Key("value","key");
map.get(myKey);
which would return a list of N items
You can create a multidimensional array by first declaring it, then creating a method to ensure that new value keys are initialized before the put. This example uses a Map with an embedded List, but you can have Maps of Maps, or whatever your heart desires.
I.e., you must define your own put method that handles new value initialization like so:
private static Map<String, List<USHCommandMap>> uSHCommandMaps = new HashMap<String, List<USHCommandMap>>();
public void putMemory() {
if (!uSHCommandMaps.containsKey(getuAtom().getUAtomTypeName()))
uSHCommandMaps.put(getuAtom().getUAtomTypeName(), new ArrayList<USHCommandMap>());
uSHCommandMaps.get(getuAtom().getUAtomTypeName()).add(this);
}