If I extract an element from a hash map through the method get(<key>) and update the extracted element, will these updates persist in the map? Or do I have to re-insert the element back to the hash map?
If you change fields of the object you got out, like this...
Thing thing = map.get(key);
thing.setOtherThing(yetAnotherThing);
then that'll update the value in the map.
On the other hand, if you modify the reference that you obtained by getting a value out of the map...
Thing thing = map.get(key);
thing = doSomethingWith(thing);
then you need to put it back into the map.
If you modify the object obtained by the Map.get(K) method, the object does not need to be re-inserted. However, if you change a key in a way that the hashCode() function is affected, then you need to remove the map entry before modifying the key and then you can put back your value using your new key.
Consider the following map corruption case:
Map<List<String>, String> map = new HashMap<List<String>, String>();
List<String> key1 = new ArrayList<String>();
key1.add("key1");
map.put(key1, "value1");
System.out.println(map.get(key1)); //prints "value1"
key1.add("buzz2");
System.out.println(map.get(key1)); //prints "null"
List<String> k = map.keySet().iterator().next();
System.out.println(map.get(k)); //prints "null"
Morale of the story: for maps, always use immutable keys like String or int.
Related
I have a map of values. The values are limited to just 3 possibilities ( "A", "B", "C") . I will have some 100 entries for this map.
Map<String, String> map = new HashMap<>();
map.put("key1","A");
map.put("key2","B");
map.put("key3","C");
map.put("key4","A");
map.put("key5","B");
.
.
.
The only purpose of this map would be a function where I get the key as input and I need to return one of the three "A","B","C" or null if the key has no value. My lookup will only be based on the key here.
I cannot decide if I should repeat the values and construct a flat map as above, or to use a Map<String, List<String>> where the key would be the three values. As in
Map<String, List<String>> map = new HashMap<>();
map.put("A",Arrays.asList("key1","key2"));
map.put("B",Arrays.asList("key3","key4"));
map.put("C",Arrays.asList("key5","key6"));
Or, do I use 3 separate List<String> variables and check using contains each time. As in
List<String> A_LIST = Arrays.asList("key1","key2");
List<String> B_LIST = Arrays.asList("key3","key4");
List<String> C_LIST = Arrays.asList("key5","key6");
Also, do I use an enum/static Strings for the values here and repeat them while constructing the Map? What would be the proper way to do this? Any advice would be useful.
I'm not sure if I understood your problem. But I think the get(key) method of your map should be enough. If there is no entry in the map it will return null.
I would only change the value so it is an Enum and you can be sure that there are no other values besides A, B and C.
Map<String,String> mapp=new HashMap<>();
mapp.put("1", "abc");
mapp.put("1", "def");
System.out.println(mapp.size());
System.out.println(mapp.get("1"));
System.out.println(mapp);
o/p
1
def
{1=def}
How to get 'abc' value and wheather its present in the map as size is 1.
Can this be a case of hash collision, as the key is same can it produce same hashcode and store in the same index?
mapp.put("1", "def"); would return the previous value - "abc" - of the key "1".
You can see it with:
System.out.println(mapp.put("1", "def"));
Afterwards, there's no way to obtain the original value of the "1" key, since it has been overwritten.
This is specified in the Javadoc of put:
V java.util.Map.put(K key, V value)
Associates the specified value with the specified key in this map (optional operation). If the map previously contained a mapping for the key, the old value is replaced by the specified value. (A map m is said to contain a mapping for a key k if and only if m.containsKey(k) would return true.)
Returns:
the previous value associated with key, or null if there was no mapping for key.
Once you have clobbered a key's value in a hashmap, that value is for all intents and purposes gone. If you have a need to keep track of multiple values associated with a key, then consider using a map of some sort of collection:
Use a map of lists:
Map<String, List<String>> mapp = new HashMap<>();
List<String> list = new ArrayList<>();
list.add("abc");
list.add("def");
mapp.put("1", list);
I'm trying to use HashMap and Hastable with a List of Object as Key.
Please see below a simplified version of my code which doesn't work.
When I debug this code, I expect having 3 items in the TestMap4 Object but there is only 1.
List<String> lst = new ArrayList<>();
lst.add("Hello");
lst.add("World");
Map<List<String>, Integer> testMap4 = new HashMap<List<String>, Integer>();
testMap4.put(lst, 1);
testMap4.put(lst, 2);
testMap4.put(lst, 5);
What happens when I put a new item into the HashMap object ? why doesn't it work ?
I obtain the same result with this new example below. (Each List countains the same 2 String)
List<String> lst = new ArrayList<>();
lst.add("Hello");
lst.add("World");
List<String> lst2 = new ArrayList<>();
lst2.add("Hello");
lst2.add("World");
List<String> lst3 = new ArrayList<>();
lst3.add("Hello");
lst3.add("World");
Map<List<String>, Integer> testMap4 = new HashMap<List<String>, Integer>();
testMap4.put(lst,1);
testMap4.put(lst2,2);
testMap4.put(lst3,5);
If I modify only 1 char of the 2 String, this is OK
You do not understand the concept of HashMap.
Your problem is that you are using the same key each time.
testMap4.put(lst, 1); // <----same key, different value
testMap4.put(lst, 2); // <----same key, different value
testMap4.put(lst, 5); // <----same key, different value
In Hashmap, every value that is stored in the Hashmap, there's a key that is saved with that particular value and is unique for each value stored in Hashmap
Important points about HashMap:
1- A HashMap contains values based on the key.
2- It contains only unique elements.
3- It may have one null key and multiple null values.
4- It maintains no order.
Example
HashMap<Integer,String> hm = new HashMap<>();
Secondarily, using a mutable object (a List<>) as the key results in undefined behavior if any of the lists are modified after they are inserted into the map. The hash code is calculated according to the contract for List (see the Javadoc) only when the entry is first inserted into the map. A change to the list's contents will change the hash code and you will no longer be able to find the entry.
Using a List<> (or any mutable object) as the key in a HashMap<> is a Really Bad Idea™.
It is not working because you are using same key each time for storing different value due to which all the value are getting map to same key and hashmap is only storing the last value since this value override the previous values.
HashMap calls the hashCode() method on the key-object you put in the HashMap.
As you don't have overridden it for the key class you use (List<> in your case) it calls the hashCode() method on java.lang.Objectwhich returns a unique object id.
As you put the same object three times into the Map, it is the same key you put in three times in a row.
List<String> lst1 = new ArrayList<>();
lst.add("Hello");
lst.add("World");
List<String> lst2 = new ArrayList<>();
List<String> lst3 = new ArrayList<>();
Map<List<String>, Integer> testMap4 = new HashMap<List<String>, Integer>();
testMap4.put(lst1, 1);
testMap4.put(lst2, 2);
testMap4.put(lst3, 5);
will give you three entries in your Map.
If you need a HashCode over the contents of the list for usage as HashMap keys, have a look at:
static int java.util.Objects.hash(Object... values)
static boolean java.util.Arrays.equals(Object[] a, Object[] a2)
Don't forget that you always have to override both methods. hashCode() and equals(). You will instantly drop dead, if you only override one of them!! ;)
HashMap map= new HashMap();
System.out.println(map.put(101,"john"));//null
System.out.println(map.put(101,"abhraham"));//john
If I give the key which is existing it replaces the value and returns the old value.
But if I use putAll how can I get the oldvalues?
HashMap map2=new HashMap();
map2.put(101,"Lincoln");
System.out.println(map.putAll(map2));//runtime exception
If I want the old value that has been replaced what I should use in map?
leave the printing part if i want the old value what i must do.
You can replace them one at a time using Map.put(), which will return the old value:
HashMap oldValues = new HashMap();
map2.forEach((key, value) -> {
oldValues.put(key, map.put(key, value));
});
The HashMap.putAll() method has a void return type, which is why you get the exception. You must call the HashMap.put() method for each element of the map2 variable and then either print them individually or put them in another map and then print it's content (or do what you want with them).
I want to get all the values associated with a key in Map.
For e.g,
Map tempMap = new HashMap();
tempMap.put("1","X");
tempMap.put("2","Y");
tempMap.put("3","Z");
tempMap.put("1","ABC");
tempMap.put("2","RR");
tempMap.put("1","RT");
How to retrieve all the values associated with key 1 ?
the thing you must understand is that in a Map, the key is unique.
that means that after
tempMap.put("1","X");
"1" is mapped to "X"
and after
tempMap.put("1","ABC");
"1" is mapped to "ABC" and the previous value ("X") is lost
From the HashMap javadoc:
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.
What you can do is this:
Map<String, List<String>> tempMap = new HashMap<String, List<String>>();
tempMap.put("1", new LinkedList<String>());
tempMap.get("1").add("X");
tempMap.get("1").add("Y");
tempMap.get("1").add("Z");
for(String value : tempMap.get("1")) {
//do something
}
This compartmentalizes values that correspond to the key "1" into their own list, which you can easily access. Just don't forget to initialize the list... else NullPointerExceptions will come to get you.
Yuval =8-)
can't
try using google collections's Multimap
I think you're missing something important:
Map tempMap = new HashMap();
tempMap.put("1","X");
tempMap.put("2","Y");
tempMap.put("3","Z");
tempMap.put("1","ABC"); // replaces "X"
tempMap.put("2","RR"); // replaces "Y"
tempMap.put("1","RT"); // replaces "ABC"
Also, you should use generics where possible, so your first line should be:
Map<String, String> tempMap = new HashMap<String, String>();
To do that you have to associate each key with a Set of values, with corresponding logic to create the set and enter/remove values from it instead of simple put() and get() on the Map.
Or you can use one of the readymade Multimap implementations such as the one in Apache commons.