How to iterate complicated List of Maps containing Maps - java

I'm having problems working out how to iterate this structure.
ArrayList<HashMap<String, HashMap<String, String>>> list
Can you help me work out how to walk the complete structure?
Here's what I've got to so far but where do I go next? I need to get all the way down to the deepest data.
for (HashMap<String, String> map : data)
for (Entry<String, String> entry : map.entrySet())

How about this?
ArrayList<HashMap<String, HashMap<String, String>>> list = new ArrayList<>();
for (HashMap<String, HashMap<String, String>> m : list) {
for (Map.Entry<String, HashMap<String, String>> e : m.entrySet()) {
String key1 = e.getKey();
for (Map.Entry<String, String> me : e.getValue().entrySet()) {
String key2 = me.getKey();
String value = me.getValue();
}
}
}
Note that you really should be using the interface form of the objects:
List<Map<String, Map<String, String>>> list = new ArrayList<>();
for (Map<String, Map<String, String>> m : list) {
// All Maps.
for (Map.Entry<String, Map<String, String>> e : m.entrySet()) {
// Outer key.
String key1 = e.getKey();
for (Map.Entry<String, String> me : e.getValue().entrySet()) {
// Inner key.
String key2 = me.getKey();
// The String value.
String value = me.getValue();
}
}
}

Related

Recursively increase the same nested map values if keys are already exists

My parentMap is look like something below.
HashMap<String, Integer>>> parentMap = {disabled={account={test1=22}, group={test2=10}}}
What I suppose to do is, if operationType=disabled and objectType=account or group etc and testName=test1 or test2 etc then I suppose to increase the count of test1 by 1.
I have to update the same map so that at the end I should get some statistic like there are 22 tests cases of objectType=account and 10 tests cases of objectType=group etc are disabled
I tried something below but it is going in infinite loop as I'm putting values in the map and iterating over it again.
private HashMap<String, HashMap<String, HashMap<String, Integer>>> countTags(String statType, String objectType,
String opType, HashMap<String, HashMap<String, HashMap<String, Integer>>> parentMap) {
if (!Util.isEmpty(parentMap)) {
//created new map to avoid infinite loop here but no luck :(
HashMap<String, HashMap<String, Integer>> objMap = new HashMap<>();
objMap.putAll(parentMap.get(statType));
Iterator<Entry<String, HashMap<String, Integer>>> it = objMap.entrySet().iterator();
while (it.hasNext()) {
Entry<String, HashMap<String, Integer>> operationEntry = it.next();
HashMap<String, Integer> operationMap = operationEntry.getValue();
Set<String> opKeySet = operationMap.keySet();
Iterator<String> opIt = opKeySet.iterator();
while (opIt.hasNext()) {
parentMap.put(statType, countTags(objectType, opType, operationMap));
}
}
} else {
parentMap.put(statType, countTags(objectType, opType, new HashMap<String, Integer>()));
}
return parentMap;
}
private HashMap<String, HashMap<String, Integer>> countTags(String objectType, String opType, HashMap<String, Integer> tagMap) {
int testRepeatCount = tagMap.get(opType) != null ? tagMap.get(opType) : 0;
tagMap.put(opType, 1 + testRepeatCount);
HashMap<String, HashMap<String, Integer>> objMap = new HashMap<>();
objMap.put(objectType, tagMap);
return objMap;
}
I found
a.compute(key, (k, v) -> v == null ? 1 : v + 1); also some suggestions here Java map.get(key) - automatically do put(key) and return if key doesn't exist? but can I get some help how optimally I should achieve my desired outcome here?
I finally get out of my own if_else mess. this is how my final method is look a like. This helped me here Java append `HashMap` values to existing HashMap if key matches
private HashMap<String, HashMap<String, HashMap<String, Integer>>> countTags(String statType, String objectType,
String opType, HashMap<String, HashMap<String, HashMap<String, Integer>>> parentMap) {
if (!Util.isEmpty(parentMap) && parentMap.containsKey(statType)) {
// if objType is present, count the tags
if (parentMap.get(statType).containsKey(objectType)) {
HashMap<String, Integer> objMap = parentMap.get(statType).get(objectType);
HashMap<String, Integer> map = countTags(objectType, opType, objMap).get(objectType);
parentMap.get(statType).get(objectType).putAll(map);
} else {
// if objType isn't present, add that objType and count the tags
HashMap<String, HashMap<String, Integer>> map = countTags(objectType, opType,
new HashMap<String, Integer>());
parentMap.get(statType).put(objectType, map.get(objectType));
}
} else {
// first time add the new tag to calculate it's object/operation wise
// distribution
parentMap.put(statType, countTags(objectType, opType, new HashMap<String, Integer>()));
}
return parentMap;
}

Iterate List<Map<String, Object>> and add the values of object to a list using Java

Im having a List> as
[{TXNO=428, STATUS=NEW}, {TXNO=434, STATUS=NEW}, {TXNO=442, STATUS=NEW}]
I'm iterating the object as
for (Map<String, Object> map : details) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
logger.info(key+"="+value);
}
}
It prints as
TXNO=428
STATUS=NEW
TXNO=434
STATUS=NEW
TXNO=442
STATUS=NEW
How can I add TXNO values in a list? My List object finally should be [428,434, 442]
List<String> TXNOList = new LinkedList<String>();
for (Map<String, Object> map : details) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
logger.info(key+"="+value);
if(key.equals("TXNO")) {
TXNO.add(value);
}
}
}
If you need a Integer list just change the TXNOList definition to Integer and cast value to Integer: Integer.valueOf(value).
If you can use java 8, then here's an elegant solution:
List<Object> txno = mapList.stream()
.map(map -> map.get("TXNO")) // get value by key
.filter(Objects::nonNull) // check if not null
.collect(Collectors.toList()); // collect to list
You can do this way :-
List<Object> TXList=new ArrayList<Object>();
for (Map<String, Object> map : details) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if(key.equals("TXNO"))
TXList.add(value);
}
}

Group the map values to avoid duplicate [duplicate]

This question already has answers here:
Reverse HashMap keys and values in Java
(12 answers)
Closed 5 years ago.
I have a Map(map1) whose key is another map(map2) and value is string.
The value of map1 has several duplicate, so I must group them and set as key in another map3 whose value has to be map2.
eg:
map1 { [[a,b],xyz], [[c,d],wrt] , [[e,f],xyz] , [[r,m],xyz] }
output should be :
map3 { [ xyz,[ [a,b],[e,f],[r,m] ] ] , [ wrt,[ [c,d] ]
can i obtain like this ?
try MultiValueMap from (commons-collections) library
Map map1 = new HashMap<String[], String>();
map1.put(new String[]{"a", "b"}, "xyz");
map1.put(new String[]{"c", "d"}, "wrt");
map1.put(new String[]{"e", "f"}, "xyz");
map1.put(new String[]{"c", "d"}, "xyz");
MultiValueMap map2 = new MultiValueMap();
for(String[] key: map1.keySet()) {
String value = map1.get(key);
map2.add(value, key);
}
// now you got map2 as you want
NO, Though you can declare it but while using it, it may allow same keys(human readable). Because Map do not override Object's equals method your key comparison will be on JVM's object level (it may be different for objects with same values in them).
You can use the stream API to solve it:
Map<String, List<Map<String, String>>> map3 = map.entrySet().stream()
.collect(Collectors.groupingBy(Entry::getValue,
Collectors.mapping(Entry::getKey,
Collectors.toList())));
Explanation:
The entries will be grouped by its values (groupingBy(Entry::getValue).
But the values should not be a list of entries so the downstream is necessary. This is the list of keys of the original map.
It is not clear from your post what do you mean by map2, but let's assume you would like to use each Map.Entry<String, String> entry from map2 for each key for map1.
The following code is Java 7, it's a bit verbose. It could be done shorter with Java 8 streams, I guess.
public class MapReverser {
private Map<Map.Entry<String, String>, String> map1 = new HashMap<>();
private Map<String, String> map2 = new LinkedHashMap<>();
private void prepareMaps() {
map2.put("a", "b");
map2.put("c", "d");
map2.put("e", "f");
map2.put("r", "m");
String[] valueArray = { "xyz", "wrt", "xyz", "xyz" };
int i = 0;
for (Map.Entry<String, String> entry : map2.entrySet()) {
map1.put(entry, valueArray[i]);
i++;
}
}
public Map<String, List<Map.Entry<String, String>>> reverse() {
Map<String, List<Map.Entry<String, String>>> reversedMap = new HashMap<>();
for (Map.Entry<Map.Entry<String, String>, String> entry : map1.entrySet()) {
List<Map.Entry<String, String>> reversedMapValue = reversedMap.get(entry.getValue());
if (reversedMapValue == null) {
reversedMapValue = new ArrayList<>();
}
reversedMapValue.add(entry.getKey());
reversedMap.put(entry.getValue(), reversedMapValue);
}
return reversedMap;
}
private void printResult(Map<String, List<Map.Entry<String, String>>> reversedMap) {
for (Map.Entry<String, List<Map.Entry<String, String>>> entry : reversedMap.entrySet()) {
System.out.println("Key: \n" + entry.getKey());
System.out.println("Values:");
List<Map.Entry<String, String>> valuesList = entry.getValue();
for (Map.Entry<String, String> value : valuesList) {
System.out.println(value );
}
System.out.println("\n");
}
}
public static void main(String[] args) {
MapReverser mapReverser = new MapReverser();
mapReverser.prepareMaps();
Map<String, List<Map.Entry<String, String>>> reversedMap = mapReverser.reverse();
mapReverser.printResult(reversedMap);
}
}

Map String values processing

I have Map like
for (Emp emp: findAllEmp()) {
Map<String, String> map = objectMapper.convertValue(emp, HashMap.class);
}
which has values as
projects = {projectId=24, projectName=K245}
I would like to add if projects is not null, then add this to
map.put("projectId", map.get("projects.projectId}"));
map.put("projectName",map.get("projects.projectName}"));
When I see the output, projects.projectId and projects.projectName is always null.
How do I resolve this?
And how can I dynamically add values instead of hard coding projects.projectId?
Try to understand,
projects = {projectId=24, projectName=K245} is nothing but
Map<String, Map<String,Object>>
Map<"projects", Map<"projectId",24>>
Map<"projectName",K245>>
Just iterate over a map,
Map<String, String> map = objectMapper.convertValue(emp, HashMap.class);
Map<String, Object> myMap = new HashMap<String, Object>();
if (null != map && map.size() > 0) {
for (Map.Entry<String, String> entry : map.entrySet())
myMap.put(entry.getKey(), entry.getValue());
}
myMap will contain data as
Map<"projectId",24>
<"projectName",K245>
Also you can iterate and check for value if value is instanceOf Map
Map<String, Object> myMap = null;
if (null != map && map.size() > 0) {
for (Map.Entry<String, Object> entry : map.entrySet())
if (entry.getValue() instanceof java.util.Map) {
myMap = (Map<String, Object>) entry.getValue();
}
}
or assign value to myMap and iterate over it.

Converting a HashMap<String, ArrayList<String>> to a HashMap <String, String>

Please, help me convert a HashMap<String, ArrayList<String>> to HashMap <String, String>, where each ArrayList should be converted into one String that contains the ArrayList's elments.
I believe that this is what you are looking for.
//HashMap<String, ArrayList<String>> hashMap;
//initialized somewhere above
HashMap<String, String> newHashMap = new HashMap<>();
for (Map.Entry<String, ArrayList<String>> entry : hashMap.entrySet())
{
newHashMap.put(entry.getKey(), entry.getValue().toString());
}
Not sure if your issue was with toString() or how to iterate over a HashMap, if it was the latter, here's how to iterate over a map.
Here's a from-start-to-finish example:
ArrayList<String> al = new ArrayList<>();
al.add("The");
al.add("End");
HashMap<String, ArrayList<String>> hashMap = new HashMap<>();
hashMap.put("This is", al);
HashMap<String, String> newHashMap = new HashMap<>();
for (Map.Entry<String, ArrayList<String>> entry : hashMap.entrySet())
{
newHashMap.put(entry.getKey(), entry.getValue().toString());
}
System.out.println(newHashMap.toString());
//prints {This is=[The, End]}

Categories