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;
}
Related
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);
}
}
So I am trying to use HashMaps by specififying:
HashMap totalAtt = new HashMap<String, Integer>();
But when I try to add two of the Integers, it gives me an error saying bad operand. How can I add the integers I retrieve from this HashMap without a compiler error or warning?
Edit: Replaced some code, no longer getting compiler error, rather warning of unchecked or unsafe operations
public HashMap<String, Integer> getAttrib()
{
HashMap<String, Integer> totalAtt = new HashMap();
//Creates key values and initializes them to 0
totalAtt.put("strength", 0);
totalAtt.put("dexterity", 0);
totalAtt.put("constitution", 0);
totalAtt.put("intelligence", 0);
totalAtt.put("wisdom", 0);
totalAtt.put("charisma", 0);
HashMap<String, Integer> sAtt;
for(Sprite s: itemList)
{
//iterates through items and counts their attributes
sAtt = s.getAttrib();
totalAtt.put("strength", totalAtt.get("strength") + sAtt.get("strength"));
totalAtt.put("dexterity", totalAtt.get("dexterity") + sAtt.get("dexterity"));
totalAtt.put("constitution", totalAtt.get("constitution") + sAtt.get("constitution"));
totalAtt.put("intelligence", totalAtt.get("intelligence") + sAtt.get("intelligence"));
totalAtt.put("wisdom", totalAtt.get("wisdom") + sAtt.get("wisdom"));
totalAtt.put("charisma", totalAtt.get("charisma") + sAtt.get("charisma"));
}
return totalAtt;
}
From Sprite class:
public HashMap<String, Integer> getAttrib()
{
return attrib;
}
Change
HashMap totalAtt = new HashMap<String, Integer>();
to
HashMap<String, Integer> totalAtt = new HashMap<>();
and
HashMap sAtt
to
HashMap<String, Integer> sAtt
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();
}
}
}
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]}
How do I put values in this map?
public static Map<String, TreeMap<String, SomeClass>> myMap=Collections.synchronizedMap(new TreeMap<String, TreeMap<String,SomeClass>>());
First you need to make sure the "inner map" exists, then you can put values into it:
String outerKey = "exampleKey1";
String innerKey = "exampleKey2";
SomeClass innerValue = new SomeClass();
TreeMap<String, SomeClass> innerMap = myMap.get(outerKey);
if (innerMap == null) {
innerMap = Collections.synchronizedMap(new TreeMap<String, SomeClass>());
myMap.put(outerKey, innerMap);
}
innerMap.put(innerKey, innerValue);
You should also consider changing the type to:
public static Map<String, SortedMap<String, SomeClass>> myMap = ...
// ^^^^^^^^^
or just Map depending on if you need the sorted property.
TreeMap<String, SomeClass> map = myMap.get(key1)
if(map == null) {
map = Collections.synchronizedMap(new TreeMap<String, SomeClass>());
myMap.put(key1, map);
}
map.put(key2, value);
TreeMap<String, SomeClass> value = new TreeMap<String, SomeClass>();
myMap.put("key", value);