Given the following Java HashMap:
HashMap<String, Integer> map = new HashMap<String, Integer>();
The following statement gives me a 'backed' set of the maps keys:
Set<Integer> keys = map.keySet();
but suppose I'd like a copy of the key set which I can manipulate without affecting the map. Is there a better/more correct way than
Set<Integer> keys = new HashSet<Integer>();
for( Integer key : map.keySet() )
keys.add( key );
?
There's a slightly simpler way:
Set<Integer> keys = new HashSet<Integer>(map.keySet());
...which just makes a copy in a single line.
Set<Integer> keys = new HashSet<Integer>(map.keySet());
This will initialise a Set which contain exactly the same elements in the map's key set which is passed into the HashSet constructor.
Related
I'm trying to create a HashMap from values of a HashSet (which itself is stored as values in a HashMap).
I'm not sure whether to Iterate or use a for loop.
Example:
newMap = new HashMap<String, HashSet<String>>();
HashSet<String> boxing = new HashSet<String>();
newMap.put("fighting", boxing);
boxing.add("jab");
boxing.add("hook");
boxing.add("uppercut");
Now I need to iterate or loop through so that each value in the 'boxing' HashSet creates a new HashMap with the value as the key for the new map.
So newMap1 would have 'jab' as the key, newMap2 would have 'hook' as the key and so on.
Any help is appreciated.
Since Java 9 you can do this:
Map<String, Set<String>> newMap = Map.of("fighting", Set.of("jab","hook","uppercut"));
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!! ;)
One more question about HashMap<> in Java:
I have the following
Map<String, Set<Integer>> myWordDict = new HashMap<String, Set<Integer>>();
After storing data into the variable myWordDict, I want to iterate through the HashMapValues, and add each value to a new Set variable?
When I try to do Set<Integer> newVariable = myWordDict.entrySet(), it seems the data type is incompatible.
So my question is essentially:
how to convert HashMap values or entrySet() to Set ?
Thanks
Try:
Set<Integer> newVariable = mywordDict.keySet();
or
Set<Integer> newVariable = new HashSet<Integer>(myWordDict.values());
Your declaration should be like below. It will convert your map values to Collection
Collection<Set<Integer>> newVariable = myWordDict.values();
What does entrySet returns?
public Set<Map.Entry<K,V>> entrySet()
Returns a Set view of the mappings contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa.
If you want iterate over the myWordDict hash map then just
for(Map.Entry<String, Set<Integer>> entry : myWordDict.entrySet())
{
Set<Integer> newVariable = entry.getValue();
}
Related links
Map.Entry#getValue()
If you need all the values as a Set of Integers and not as a Set of Set, then you could do something like this
Set<Integer> newVariable = new HashSet<Integer>();
for (Set<Integer> set : myWordDict.values()) {
newVariable.addAll(set);
}
Or if you want them as a Set of Set, you need to do something like this
Set<Set<Integer>> newVariable = new HashSet<Set<Integer>>();
newVariable.addAll(myWordDict.values());
flatMap will help you:
myWordDict.values().stream().flatMap(Set::stream).collect(Collectors.toSet());
use myWordDict.values(), not myWordDict.entrySet(). values is a set of the map's values, whereas entrySet is a set of its mappings (it is a set of java.util.map.Entry objects, each of which describes a key and a value).
Assuming that you want to add all values from the sets in the map your approach to do it is to use addAll method:
Set<Integer> newVariable = new HashSet<Integer>();
for (Set<Integer> set : myWordDict.values()) {
newVariable.addAll(set);
}
Map<Integer,String> map1 = new HashMap<Integer,String>();
map1.put(1, "Rakesh");
map1.put(2, "Amal");
map1.put(3, "Nithish");
Set<Entry<Integer,String>> set1 = map1.entrySet();
So, I came up with an iterator to iterate through the value Set
I have this data structure
Map<String, Set<Integer>> myWordDict = new HashMap<String, Set<Integer>>();
I created
Iterator mapIterator = myWordDict.entrySet().iterator();
Then just use a while() loop to add individual value to a new Set variable. I am not sure this is the most efficient way, but it works for my needs.`
Map<String, String> map = new HashMap<String, String>();
map.put("1", "xyz");
map.put("1", "abc");
map.put("1", "cde");
map.put("2", "err");`
`
for the above map I want to get all the values associated with the key 1. Expected output.
Key:: 1 values are:: xyz, abc, cde
Order of the values doesn't important.
In a Map the key should always be unique. If you associate a new value to an existing key, it will overwrite the value of the existing entry.
You might need to check the interface for Map#put(K, V) method.
If the map previously contained a mapping for the key, the old value
is replaced by the specified value.
So in your case your map will always have "cde" as the value for the key "1".
Use MultiMap
MultiMap mapValue = new MultiValueMap();
mapValue.put("1", "xyz");
mapValue.put("1", "abc");
mapValue.put("1", "cde");
mapValue.put("2", "err");
System.out.println("Map : " + mapValue);
Output: Map : {2=[err], 1=[xyz, abc, cde]}
A map can not have duplicate keys.
If you want to implement what you describe in question. First you need to use multimaps
What you are doing is wrong.
Map doesn't allow duplicates.
So one key -----------> one value
If you see docs of put()
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.)
You can print the values of each key and value like
Ex:
Map<String, String> map = new HashMap<String, String>();
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
In Map you can't have duplicate keys. so In your case final value put for key 1. "cde" will remain in Map
You can do some thing like following to achive what you are expecting
Map<String, List<String>> map = new HashMap<>();
List<String> list=new ArrayList<>();
List<String> list1=new ArrayList<>();
list.add("xyz");
list.add("abc");
list.add("cde");
list1.add("err");
map.put("1", list);
map.put("2",list1);
System.out.println(map.get("1"));
HashMap::put overrides the old value associated with the key. You have to put a List in each map entry and insert new values in the appropriate list.
From the java documentation about HashMap.put(K key, V value) method:
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.
So you can't do that.
This is impossible, a map is called a map because it maps one key value to a value. Multiple keys can map to the same value but not the other way around.
What you probably want is a map which maps to a List<String> instead:
final Map<String, List<String>> map = new HashMap<>();
if (map.get("1") == null) {
map.put("1", new ArrayList<String>());
}
map.get("1").add("xyz");
// ...
A helper function for adding might be convenient
public static <K, V> void add(final K key, final V value, final Map<K, List<V>> map)
{
if (map.get(key) == null) {
map.put(key, new ArrayList<V>());
}
map.get(key).add(value);
}
You can not do this with this type of Map. The key in map must be unique.
To be able to do that you should declare a map, where key is string but values are collections of Strings.
Map<String,Collection<String>> map = new HashMap<String,Collection<String>>();
The to list values from it you can do this
for(String valueOfKey : map.get("key") {
//print or something else
}
Note that to add some values to it you must first check that key is already stored and if not then fist declare a collection.
if(map.contains("key") == false) {
map.put(new ArrayList<String>());
}
map.get("key").add("value");
As this is well know design you might be interest in guava framework and Multimap
The benefit of this class is that it already has implemented the logic how to add and retrieve values from it.
You could do something like:
for (String k : map.keySet())
System.out.println(k);
This would print the keys in the HashMap, but without any guarantees on order.
You can not have duplicate key for a hash map see the below S.O for What happens for duplicate keys in HashMap
I am working in Java, and have declared two maps as follow:
private Map<MyCustomClass, Integer> map1, map2;
map1 = new HashMap<MyCustomClass, Integer>();
map2 = new HashMap<MyCustomClass, Integer>();
//adding some key value pair into map1
//adding some key value pair into map2
private ArrayList<MyCustomClass> list = new ArrayList<MyCustomClass>();
Now i want to insert the keys of both map in the above declared ArrayList. Is there any built-in method exist for this or i need to writes some custom code?
To add everything:
list.addAll(map1.keySet());
list.addAll(map2.keySet());
To add only unique keys:
Set<MyCustomClass> keys = new HashSet(map1.keySet());
keys.addAll(map2.keySet());
list.addAll(keys);
References: List.addAll(Collection c);
HashMap.keySet()
list.addAll(map1.keySet());
list.addAll(map2.keySet());
keySet() gets all the keys from the map and returns them as a set. The addAll then adds that set to your list.