Printing HashMap of HashMaps : Map.Entry or java8 - java

I have a method which returns out hashmap of hashmaps
HashMap<String, HashMap<String, String>> mapofmaps = abcd(<String>, <Integer>);
I am trying to print the the outer hashmap using the following code
for (Entry<String, HashMap<String, String>> entry : mapofmaps.entrySet()) {
String key = entry.getKey();
System.out.println(key);
HashMap<String, String> value = entry.getValue();
System.out.println(key + "\t" + value);
}
I would like to iterate through the inner map. What would be the entryset variable there (??? in the code).
for (Entry<String, HashMap<String, String>> entry : mapofmaps.entrySet()) {
String key = entry.getKey();
System.out.println(key);
for(Entry<String, HashMap<String, String>> entry : ????.entrySet()){
HashMap<String, String> value = entry.getValue();
System.out.println(key + "\t" + value);
}}
Is my logic for printing the hashmaps correct? or is there a better way to do that?

It will be entry.getValue().entrySet()
so
for(Entry<String, String> innerEntry : entry.getValue().entrySet()){
then you can use
String key = innerEntry.getKey();
String value = innerEntry.getValue();
It is worth mentioning that, this can also be done Using java 8 Streams and lambda expressions
HashMap<String, HashMap<String, String>> mapofmaps = new HashMap<>();
HashMap<String,String> map1 = new HashMap<>();
map1.put("map1_key1", "map1_value1");
HashMap<String,String> map2 = new HashMap<>();
map2.put("map2_key1", "map2_value1");
mapofmaps.put("map1", map1);
mapofmaps.put("map2", map2);
// To print the keys and values
mapofmaps.forEach((K,V)->{ // mapofmaps entries
V.forEach((X,Y)->{ // inner Hashmap enteries
System.out.println(X+" "+Y); // print key and value of inner Hashmap
});
});
mapofmaps.forEach((K,V) : This expects a lambda expressions which takes two inputs i.e Key (String) and Value (HashMap)
V.forEach((X,Y)->{ : As this is applied on inner (V: fetched through previous foreach) hashmap so both Key and Value will be strings
Reference for further reading :
Lambda Expressions
Map foreach description

A Straight forward example with data
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 10);
map.put("Motorolla", 20);
map.put("RealMe", 30);
map.put("Oppo", 40);
map.put("Sony", 50);
map.put("OnePlus", 60);
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ", Stock : " + entry.getValue());
}
Using lambda expression
map.forEach((K,V) -> System.out.println(K + ", Stock : " + V));

Related

Hashmap. Find key(s) which have same values between two hashmaps

Lets consider we have two hashmaps as below:
HashMap<String, Integer> map1 = new HashMap<>();
map1.put("vishal", 10);
map1.put("sachin", 30);
map1.put("vaibhav", 20);
HashMap<String, Integer> map2 = new HashMap<>();
map2.put("Raja", 10);
map2.put("John", 30);
map2.put("Krishna", 20);
The "vaibhav" from map1 and "krishna" from map2 have the same values.
I need to find the keys from both the maps, which have the same values. In this case, "vaibhav" and "Krishna".
Thanks.
Group by values and store keys in list:
Stream.of(map1.entrySet(), map2.entrySet())
.flatMap(Collection::stream)
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(
Map.Entry::getKey,
Collectors.toList()
)
));
It will create:
{20=[vaibhav, Krishna], 10=[vishal, Raja], 30=[sachin, John]}
UPDATE
Other approach
Map<Integer, List<String>> collect = new HashMap<>();
map1.entrySet().forEach(e -> collect
.computeIfAbsent(e.getValue(), k -> new ArrayList<>())
.add(e.getKey()));
map2.entrySet().forEach(e -> collect
.computeIfAbsent(e.getValue(), k -> new ArrayList<>())
.add(e.getKey()));
You can improve the time complexity to O(n + m) where n is the size of first map and m is the size of the second map.
We can achieve this by making values as keys and keys as values.
Steps:
Iterate over each map.
Store all current map values in a new map and collect all keys who have that value in a list and put the current value with this list in the new map.
Now, iterate over any of the new map collections and get the common keys and it's respective values for printing.
Snippet:
private static void showCommonValueKeys(HashMap<String, Integer> map1,HashMap<String, Integer> map2){
Map<Integer,List<String>> map1Collect = flipKeyValue(map1);
Map<Integer,List<String>> map2Collect = flipKeyValue(map2);
for(Map.Entry<Integer,List<String>> m : map1Collect.entrySet()){
int key = m.getKey();
if(map2Collect.containsKey(key)){
System.out.println("For value " + key);
System.out.println("First map keys: " + m.getValue().toString());
System.out.println("Second map keys: " + map2Collect.get(key).toString());
System.out.println();
}
}
}
private static Map<Integer,List<String>> flipKeyValue(HashMap<String, Integer> map){
Map<Integer,List<String>> mapCollect = new HashMap<>();
for(Map.Entry<String,Integer> m : map.entrySet()){
String key = m.getKey();
int val = m.getValue();
mapCollect.putIfAbsent(val,new ArrayList<>());
mapCollect.get(val).add(key);
}
return mapCollect;
}
Demo: https://onlinegdb.com/SJdcpbOXU
This can be achieved through two for loops with a complexity of n*m, where n.m is the size of each map.
Map<String, String> map1 = new HashMap<>();
map1.put("santhosh", "1");
map1.put("raja", "2");
map1.put("arun", "3");
Map<String, String> map2 = new HashMap<>();
map2.put("kumar", "1");
map2.put("mani", "1");
map2.put("tony", "3");
for (Map.Entry<String, String> entry1 : map1.entrySet()) {
String key1 = entry1.getKey();
String value1 = entry1.getValue();
for (Map.Entry<String, String> entry2 : map2.entrySet()) {
String key2 = entry2.getKey();
String value2 = entry2.getValue();
if (value1 == value2) {
System.out.println(key1 + " " + key2);
}
}
Thanks.

Java: Iterate through a HashMap which is inside another HashMap

I want to iterate through a HashMap which is inside another HashMap
Map<String, Map<String, String>> PropertyHolder
I was able to iterate through the parent HashMap as following,
Iterator it = PropertyHolder.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
System.out.println("pair.getKey() : " + pair.getKey() + " pair.getValue() : " + pair.getValue());
it.remove(); // avoids a ConcurrentModificationException
}
but could not able to iterate through the child Map, It can be done by converting pair.getValue().toString() and separated using , and =. Is there any other way of iterating it?
for (Entry<String, Map<String, String>> entry : propertyHolder.entrySet()) {
Map<String, String> childMap = entry.getValue();
for (Entry<String, String> entry2 : childMap.entrySet()) {
String childKey = entry2.getKey();
String childValue = entry2.getValue();
}
}
You could iterate the child map similar to how you've done the parent:
Iterator<Map.Entry<String, Map<String, String>>> parent = PropertyHolder.entrySet().iterator();
while (parent.hasNext()) {
Map.Entry<String, Map<String, String>> parentPair = parent.next();
System.out.println("parentPair.getKey() : " + parentPair.getKey() + " parentPair.getValue() : " + parentPair.getValue());
Iterator<Map.Entry<String, String>> child = (parentPair.getValue()).entrySet().iterator();
while (child.hasNext()) {
Map.Entry childPair = child.next();
System.out.println("childPair.getKey() : " + childPair.getKey() + " childPair.getValue() : " + childPair.getValue());
child.remove(); // avoids a ConcurrentModificationException
}
}
I've presumed you want to call .remove() on the child map, which will lead to a ConcurrentModificationException if done while looping the entrySet - it looks as though you discovered this already.
I've also swapped out your use of casting with strongly-typed generics as suggested in the comments.
It's obvious - you need two nested loops:
for (String key1 : outerMap.keySet()) {
Map innerMap = outerMap.get(key1);
for (String key2: innerMap.keySet()) {
// process here.
}
}

Iterate over List<Map<String, String>> in Java

I'm trying to iterate List<Map<String, String>> in Java. However, I'm not able to iterate it properly. Can any one guide me?
Iterator it = list.iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry) it.next();
System.out.println(pairs.getKey() + " = " + pairs.getValue());
}
Thanks,
public static void main(String[] args) {
List<Map<String, String>> myListOfMaps = new ArrayList<Map<String, String>>();
Map<String, String> map1 = new HashMap<String, String>();
map1.put("Fname", "Ankur");
Map<String, String> map2 = new HashMap<String, String>();
map2.put("Lname", "Singhal");
myListOfMaps.add(map1);
myListOfMaps.add(map2);
for (int i = 0 ; i < myListOfMaps.size() ; i++) {
Map<String, String> myMap = myListOfMaps.get(i);
System.out.println("Data For Map" + i);
for (Entry<String, String> entrySet : myMap.entrySet()) {
System.out.println("Key = " + entrySet.getKey() + " , Value = " + entrySet.getValue());
}
}
}
output
Data For Map0
Key = Fname , Value = Ankur
Data For Map1
Key = Lname , Value = Singhal
Forget using the iterator directly, why not simply this:
List<Map<String,String>> l = new ArrayList<>();
...
// add map elements to list
...
for (Map<String,String> m:l) {
for (Map.Entry<String,String> e:m.entrySet()) {
String key = e.getKey();
String value = e.getValue();
// Do something with key/value
}
}
This is called an Enhanced for Loop. Internally it will handle it as a for loop traversing the iterator of any collection, or any other implementation of the Iterable Interface.
It was already used for traversing the Map Entries in one answer, so why not for the list of maps?
Of course, for nested collections, you also need to know how to nest your for-loops (how you put one for loop inside the other).
You iterate over a list with elements of type Map<String, String>. So casting to Map.Entry will give you a ClassCastException.
Try it like this
Iterator it = list.iterator();
while (it.hasNext()) {
Map<String, String> map = (Map<String, String>) it.next();
for (Map.Entry entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
It would be easier for you, if you didn't use the raw types Iterator and Map.Entry. Use generics wherever possible. So the code would look like this:
Iterator<Map<String, String>> it = list.iterator();
while (it.hasNext()) {
Map<String, String> map = it.next(); //so here you don't need a potentially unsafe cast
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
list has no entySet() method!
Try this:
final Iterator<Map<String, String>> it = list.iterator();
while (it.hasNext())
{
Map<String, String> mapElement = it.next();
// do what you want with the mapElement
}
Of course, you will need another loop to iterate over the elements in the map.

Get value of HashMap within TreeMap

I've got a TreeMap that stores a HashMap inside of it. I feel like I should be able to find this, but I just can't seem to find it on Google.
I've got a TreeMap with a HashMap stored inside of it, I iterate over it like so:
while (i.hasNext()) {
Map.Entry me = (Map.Entry) i.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
That will print out an output (example line):
I/System.outīš• 32: {walks=32, pic=http://****/images/walkers/chase.png, name=Chase, dist=6096.8589024135445}
I'm wondering how to now grab pic, name, dist from this HashMap.
Edit: I'm not understanding where people missed the point. I put a HashMap into the TreeMap. Inside of the TreeMap is a HashMap. I guess I can show you what a HashMap is, but you guys know that already!
TreeMap dist_mp=new TreeMap();
Map<String, String> mp1 = new HashMap<String,String>();
mp1.put("dist", distanceInMiles + "");
mp1.put("name", obj.getString("first_name"));
mp1.put("pic", obj.getString("pic"));
mp1.put("walks", obj.getString("walks"));
dist_mp.put(distanceInMiles, mp1);
All you need is a cast to the TreeMap values to a Map again:
while (i.hasNext()) {
Map.Entry me = (Map.Entry) i.next();
System.out.print(me.getKey() + ": ");
// Cast to a Map again
Map<String, String> mp = (Map<String, String>) me.getValue();
// get() works now
System.out.print("name = " + mp.get("name"));
System.out.print("pic = " + mp.get("pic"));
System.out.println("dist = " + mp.get("dist"));
}
Need to iterate twice, one for TreeMap and then for HashMap
public static void main(String[] args) {
TreeMap<String, Map<String, String>> dist_mp = new TreeMap<String, Map<String, String>>();
Map<String, String> mp1 = new HashMap<String, String>();
mp1.put("dist", "6096.8589024135445");
mp1.put("name", "Chase");
mp1.put("pic", "http://****/images/walkers/chase.png");
mp1.put("walks", "32");
dist_mp.put("32", mp1);
for (Map.Entry<String, Map<String, String>> entry : dist_mp.entrySet()) {
String key = entry.getKey();
System.out.println(key);
Map<String, String> myMap = entry.getValue();
for (Map.Entry<String, String> entry1 : myMap.entrySet()) {
System.out.println(entry1.getKey() + " => " + entry1.getValue());
}
}
}
output
32
walks => 32
name => Chase
pic => http://****/images/walkers/chase.png
dist => 6096.8589024135445
Your HashMap seems to be holding an object of some class, which is depicted here:
{walks=32, pic=http://****/images/walkers/chase.png, name=Chase, dist=6096.8589024135445}
Identify the class, and if getter methods are available for pic, name, dist, then use them.
I think you are just asking how to get the value associated with a key:
map.get("pic");
You want me.getValue().get("pic"), me.getValue().get("name") and me.getValue().get("dist").
This assumes that you're using generics, that your TreeMap is declared as a Map<Integer, HashMap<String, String>> and that your Map.Entry that you iterate with is declared as a Map.Entry<Integer, HashMap<String, String>>.
Also, you could iterate more easily with a for-each loop.
Map<Integer, HashMap<String, String>> theTreeMap = new TreeMap<>();
// Populate the map here.
for (Map.Entry<Integer, HashMap<String, String>> me : theTreeMap.entrySet()) {
System.out.println(me.getValue().get("pic"));
System.out.println(me.getValue().get("name"));
System.out.println(me.getValue().get("dist"));
}

issue with hashmap getting concurrent modification exception

I am getting the below error while using map and performing some remove.How to avoid this ?
Caused by: java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
at java.util.HashMap$EntryIterator.next(HashMap.java:834)
at java.util.HashMap$EntryIterator.next(HashMap.java:832)
Map<FormField, Object> ItemMap = domainItem.getValues();
for (Map.Entry<FormField, Object> ValMap : ItemMap.entrySet()) {
List<Field> groupIdList = Mapper.getGroupId(groupFieldId);
for (Field field : groupIdList) {
ItemMap.put(new FormField(field), domainItem.getDomainItemLinkId());
}
ItemMap.remove(ValMap.getKey());
}
Update:
Use Iterator and ConcurrentHashMap to avoid this scenario
Following won't throw exception
Map<Integer, String> map = new ConcurrentHashMap<Integer, String>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");
map.put(4, "d");
for (Iterator<Integer> keys = map.keySet().iterator(); keys.hasNext();) {
Integer key = keys.next();
String val = map.get(key);
map.remove(key);
}
or use another map while iterating and at the end copy it to source
for example:
Map<Integer, String> dummy = new HashMap<Integer, String>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");
map.put(4, "d");
dummy.putAll(map);
for (Iterator<Integer> keys = dummy.keySet().iterator(); keys.hasNext();) {
Integer key = keys.next();
String val = map.get(key);
map.remove(key);
}
System.out.println(map);
A Map is sorted by the keys in the key-value pairs. When you add or remove elements from the Map while you are iterating through them, the program essentially loses track of "where" in the Map it is.
To get around this, try making a separate, temporary transfer Map. There is also a class called Iterator which might suit your needs.
One way to avoid this issue is to iterate over a copy.
for (Map.Entry<FormField, Object> ValMap :
new HashMap<FormField, Object>(ItemMap).entrySet()) {
can be done without a copy of the map, execute this example and take a look at the code:
public static void main(String[] args)
{
System.out.println("creating map ...");
Map<String, String> dummyMap = new HashMap<>();
while (dummyMap.size() < 10)
{ dummyMap.put(String.valueOf(new Random().nextInt()), String.valueOf(new Random().nextInt())); }
System.out.println("start, map size: " + dummyMap.size() + ", keys=" + dummyMap.keySet());
System.out.print("going to remove: ");
for (Iterator<String> keys = dummyMap.keySet().iterator(); keys.hasNext(); )
{
final String key = keys.next();
// delete map entries per random
if(new Random().nextInt(3)>1)
{
System.out.print(key+" ");
keys.remove();
}
}
System.out.print("\n");
System.out.println("done, map size: " + dummyMap.size() + ", keys=" + dummyMap.keySet());
}
and take a look at this similar question.
HTH,

Categories

Resources