Hashmap's getValue returns Object - java

I've got the following data structure:
CFU66=[{Bild1=CFU6606}, {Bild2=CFU6603}, {Bild3=CFU6605}, {Bild4=CFU6601}, {Bild5=CFU6602}]
Structure: Hashmap_1(String Key, List(Hashmap_2(String Key, String Value)))
I'm trying to access the values from Hashmap_2:
// for each Hashmap_1 entry
for (Map.Entry<String, List> csvDictEntry : csvDict.entrySet()) {
// for each List in entry.getValue
for (List<HashMap> hashList : csvDictEntry.getValue()) {
// for each Hashmap_2 in List
for (HashMap<String, String> hashListDict : hashList) {
// for each entry in Hashmap_2 print Value
for (Map.Entry<String, String> entry :hashListDict.entrySet()){
System.out.println(entry.getValue());
}
}
}
}
The compiler gives the message, that csvDictEntry.getValue() in the second for-loop returns a Object instead of a Hashmap. Why?
However, I'm pretty new to Java and I'm sure there is a more convenient way to do this.

this
for (Map.Entry<String, List> csvDictEntry : csvDict.entrySet()) {
should be
for (Map.Entry<String, List<Map<String, String>>> csvDictEntry : csvDict.entrySet()) {

Just write all your types
Map<String, List<HashMap<String, String>>> csvDict = null;
for (Map.Entry<String, List<HashMap<String, String>>> csvDictEntry : csvDict.entrySet()) {
// for each List in entry.getValue
for (HashMap<String, String> hashList : csvDictEntry.getValue()) {
// for each Hashmap_2 in List
for (Map.Entry<String, String> entry : hashList.entrySet()) {
System.out.println(entry.getValue());
}
}
}
And also you have extra for loop.

Based on
for (Map.Entry<String, List> csvDictEntry : csvDict.entrySet()) {
I assume that type of csvDict is
Map<String, List> csvDict = ...;
where based on your data example CFU66=[{Bild1=CFU6606}, {Bild2=CFU6603}, {Bild3=CFU6605}, {Bild4=CFU6601}, {Bild5=CFU6602}]
it should be
Map<String, List<Map<String,String>>> csvDict = ...;
Problem with your reference type is that List is raw-type, which means that its actual type is unknown (it can store any kind of Objects) so Object is type which compiler assumes when you are trying to iterate over such list so when normally we would expect
for (Type t : List<Type>)
for raw type we are getting
for (Object o : rawList)
Other problem is way you are iterating because even if we change your reference to proper type
for (List<HashMap> hashList : csvDictEntry.getValue())
will not compile because getValue() returns List<HashMap> so your loop would iterate over HashMaps, not List of HashMaps so it should be
for (HashMap hashList : csvDictEntry.getValue())
Hint: try to avoid concrete types in generics, use parent type if it is possible, like interface or abstract type. This will allow you later easily changing actual type, for instance from HashMap to LinkedHashMap.
So your iteration should look like
for (Map.Entry<String, List<Map<String, String>>> csvDictEntry : csvDict.entrySet()) {
// for each Map in List stored as value
for (Map<String, String> hashListDict : csvDictEntry.getValue()) {
// for each entry in hmap_2 print Value
for (Map.Entry<String, String> entry : hashListDict.entrySet()) {
System.out.println(entry.getValue());
}
}
}
DEMO
BTW in Java 8 your code could be simplified to
csvDict.entrySet().stream()
.flatMap(m -> m.getValue().stream())
.flatMap(m -> m.values().stream())
.forEach(System.out::println);

As indicated by others you forgot to use <> after 'List' on your first line of code. Therefore, the compiler doesn't know what kind of elements are in those lists.
Also you're making it unnecessarily complex by iterating over entrySet when you're only interested in the values.
Map has 3 functions to iterate:
keySet() - if you're only interested in the keys
values() - if you're only interested in the values
entrySet() - if you're interested in both
So in your case...
for (Map<String,String> map : csvDict.values()) {
for (String value : map.values()) {
System.out.println(value);
}
}

Your problem is the first for,what you are currently doing is retrieving a generic list,instead of a particular list.
The declaration of entry set is:
Set<Map.Entry<K,V>> <------- entrySet()
Returns a Set view of the mappings contained in this map.
so you should reconsider chaging your first for to:
for (Map.Entry<String, List<HashMap>> csvDictEntry : csvDict.entrySet()) {

Related

Java: can't use Map.Entry to iterate over a Map?

Every Java Map iteration example I've seen recommends this paradigm:
for (Map.Entry<String, String> item : hashMap.entrySet()) {
String key = item.getKey();
String value = item.getValue();
}
However, when I attempt to do this I get a warning from my compiler:
Incompatible types: java.lang.Object cannot be converted to java.util.Map.Entry<java.lang.String, java.lang.Object>
Here's my code - the only wrinkle I see is that I'm iterating over an array of Map objects, and then iterating over the elements of the individual Map:
result = getArrayOfMaps();
// Force to List LinkedHashMap
List<LinkedHashMap> result2 = new ArrayList<LinkedHashMap>();
for (Map m : result) {
LinkedHashMap<String, Object> n = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : m.entrySet()) {
n.put(entry.getKey(),entry.getValue());
}
result2.add(n);
}
Am I missing something blatantly obvious?
This is happening because you are using raw types: a List<LinkedHashMap> instead of a List<LinkedHashMap<Something, SomethingElse>>. As a result, the entrySet is just a Set instead of a Set<Map.Entry<Something, SomethingElse>>. Don't do that.

How do I store values from List<Map<String, Object>> into separate Strings?

I have a
List<Map<String, Object>> assetSubtypeClassification
which contains the following values:
[{AssetName=HVAC, AssetSubTypeName=AHU, AssetClassificationName=Electric/Heat Recovery, FaultTypeName=No Power}]
I am looking to split this map into separate Strings for each heading. What is the best way to do this? Apologies if this is obvious as I am new to this
You probably? want to create a loop to "read" your Object so:
// go through the ArrayList
for (Map hashMap : assetSubtypeClassification) {
// for each hashmap get the key and value
for (Map.Entry<String, String> item : hashMap.entrySet()) {
String key = item.getKey();
String value = item.getValue();
}
}

Java - How to iterate over a hashmap of list of hashmap

I want to iterate over a hashmap of list of hashmap.
for example,
HashMap <String, List <HashMap<String, String> > >
How do I iterate over this map.
Please help me to find a solution.
You should probably look over your design, this sounds like something that could be structured in an easier way. Consider maybe breaking this collection up into classes.
But, in case you cannot change it now (or don't have the time), I'll offer a hand.
The easiest way is probably to break the iteration up in several steps:
Iterate over the inner HashMaps
Iterate over the lists
Iterate over the content in the inner HashMaps
Here's the basic code:
for( List<HashMap<String, String>> list : outer.values() ) {
for( HashMap<String, String> map : list ) {
for( String value : map.values() ) {
//Do something
}
}
}
Let us name your map.
HashMap<String, List<HashMap<String, String>>> map; //I'll assume it is initialized and filled with something.
for (String key : map.keySet()) {
for (HashMap<String, String> map2 : map.get(key)) {
for (String key2 : map2.keySet()) {
//do something
}
}
}
Another approach is to use nested loops through collections:
for (List<HashMap<String, String>> list : map.values()) {
for (HashMap<String, String> map2 : list) {
for (String veryInnerValue : map2.values()) {
//do something
}
}
}
The differ a bit. In case you don't need to know the key of the value, the second is better.
If you need to know key and value for each map :
Map<String, List<HashMap<String, String>>> myMap = new HashMap<String, List<HashMap<String, String>>>();
// loop for first map
for (Entry<String, List<HashMap<String, String>>> myMapEntry : myMap.entrySet()) {
System.out.println("myMap entry key" + myMapEntry.getKey() + ", key ");
// loop for list (value of entry)
for (HashMap<String, String> valueOfList : myMapEntry.getValue()) {
// loop for second map
for (Entry<String, String> entryOfMapOfList : valueOfList.entrySet()) {
System.out.println("key " + entryOfMapOfList.getKey() + " value " + entryOfMapOfList.getValue());
}
}
}

How to iterate through LinkedHashMap with lists as values

I have following LinkedHashMap declaration.
LinkedHashMap<String, ArrayList<String>> test1
my point is how can i iterate through this hash map.
I want to do this following, for each key get the corresponding arraylist and print the values of the arraylist one by one against the key.
I tried this but get only returns string,
String key = iterator.next().toString();
ArrayList<String> value = (ArrayList<String> )test1.get(key)
for (Map.Entry<String, ArrayList<String>> entry : test1.entrySet()) {
String key = entry.getKey();
ArrayList<String> value = entry.getValue();
// now work with key and value...
}
By the way, you should really declare your variables as the interface type instead, such as Map<String, List<String>>.
I'm assuming you have a typo in your get statement and that it should be test1.get(key). If so, I'm not sure why it is not returning an ArrayList unless you are not putting in the correct type in the map in the first place.
This should work:
// populate the map
Map<String, List<String>> test1 = new LinkedHashMap<String, List<String>>();
test1.put("key1", new ArrayList<String>());
test1.put("key2", new ArrayList<String>());
// loop over the set using an entry set
for( Map.Entry<String,List<String>> entry : test1.entrySet()){
String key = entry.getKey();
List<String>value = entry.getValue();
// ...
}
or you can use
// second alternative - loop over the keys and get the value per key
for( String key : test1.keySet() ){
List<String>value = test1.get(key);
// ...
}
You should use the interface names when declaring your vars (and in your generic params) unless you have a very specific reason why you are defining using the implementation.
In Java 8:
Map<String, List<String>> test1 = new LinkedHashMap<String, List<String>>();
test1.forEach((key,value) -> {
System.out.println(key + " -> " + value);
});
You can use the entry set and iterate over the entries which allows you to access both, key and value, directly.
for (Entry<String, ArrayList<String>> entry : test1.entrySet()) {
System.out.println(entry.getKey() + "/" + entry.getValue());
}
I tried this but get only returns string
Why do you think so? The method get returns the type E for which the generic type parameter was chosen, in your case ArrayList<String>.
// iterate over the map
for(Entry<String, ArrayList<String>> entry : test1.entrySet()){
// iterate over each entry
for(String item : entry.getValue()){
// print the map's key with each value in the ArrayList
System.out.println(entry.getKey() + ": " + item);
}
}

Iterate over nested (multi-dimensional) hashmap

I have a HashMap<String, Object> that looks like this when I call .toString() on it:
{somekey=false, anotherKey=someString, thirdKey={nestedKey=hello, nestedKey2=world,etc=etcetcetc}}
At a certain point in my script, I would like to iterate over the "thirdKey" set as its own map. Is there a common convention used to isolate a "nested" HashMap and use it as its own one-dimensional map?
Here's my code for recursively extracting all values from the map (and the maps within these map).
public List<Object> getValues(Map<String, Object> map) {
List<Object> retVal = new ArrayList<Object>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
Object value = entry.getValue();
if (value instanceof Map) {
retVal.addAll(getValues((Map) value));
} else {
retVal.add(value);
}
}
return retVal;
}
As Vikdor already said, I don't think there is a real convention for this.
Edit:
You could, of course, also write the keys and values into a new Map ("flattening" it). I just added the values to a List, because this way you don't run into problems when one of the nested maps uses an already present key.
No convention I'm aware of. You have to fall back to instanceof to see if the value at the key is a Map, and treat it specially if it is - in your case recursively.
I doubt if there would be a "common convention" with generics in place. It's best to move towards strongly typed programs and not use Object as either key or value of a hashmap. Then this scenario won't be encountered and one would have more organized data definitions. My two cents!
public static Map<String, Object> flatten(Map<String, Object> map) {
Map<String, Object> newMap = new HashMap<>();
for (Entry<String, Object> entry : map.entrySet()) {
if (entry.getValue() instanceof Map) {
#SuppressWarnings("unchecked")
Map<String, Object> tempMap = flatten((HashMap<String, Object>) entry.getValue());
for (Entry<String, Object> tempEntry : tempMap.entrySet()) {
newMap.put(entry.getKey()+"."+tempEntry.getKey(), tempEntry.getValue());
}
} else {
newMap.put(entry.getKey(), entry.getValue());
}
}
return newMap;
}

Categories