to retrieve values from hashmap inside a hashmap - java

i have map,inside another map is there as a value
to retrieve values from hashmap inside a hashmap
map<string,map1<string,object>>
how to get or retrieve values from marks?
{
"name": "mm",
"language known": "English",
"marks": {
"english": [
"88"
]
}
}

You can get inner map like this
Map<String, Object> innermap = outermap.get("marks");
Then use innermap to get value
String value=innermap.get("english");

If you know what key corresponds to the inner map, you should first obtain the inner map:
Map<String, Object> innerMap = outerMap.get("marks");
Then you can get key-value pairs from the inner map using a for-each loop:
for (String key : innerMap.keySet()) {
Object value = innerMap.get(key);
// do something with key and value
}

Related

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();
}
}

I want to compare the each value in a java map with another value

If a value matches with another value then, i want to get the key,value pair corresponding to that value into a new map and values that doesn't match i.e unique key,value pairs into another map.
Eg:
Map<String,Double> map = new HashMap<String,Double>();
map.put("First",123.12345); //data1
map.put("Second",234.3456); //data2
map.put("Third",576.9876); //data3
map.put("Fourth",123.12345);//data4
map.put("Fifth",234.3456); //data5
map.put("Sixth",999.8888); //data6
map.put("Seventh",677.4578); //data7
Now here (data1 and data4) values (data2 and data5) and match and i want to store these (key,value) pairs in a new Map
Similarly data3, data and data7 have unique values and i want to store these (key,value) pairs in another new Map.
Any help is appreciated.
Thanks in advance.
You grouping by the map value and collect those entry with same value into a Map.
Map<Double, Map<String, Double>> result =
map.entrySet().stream()
.collect(groupingBy(Entry::getValue, toMap(Entry::getKey, Entry::getValue)));
This will give you result like:
{
123.12345 -> {
First -> 123.12345,
Fourth -> 123.12345
},
234.3456 -> ...
}
In java 7:
Map<Double, Map<String, Double>> result = new HashMap<>();
for (Entry<String, Double> mapping : map.entrySet()) {
Double value = mapping.getValue();
if (!result.containsKey(value)) {
result.put(value, new HashMap<>());
}
// Add new pair to map
result.get(value).put(mapping.getKey(), value);
}

Java 8 nested groupingby

I have 2 issues that I can't seem to solve. The first one is I need a way to have dynamic nested grouping by where there could be 1-n nested groups that the user can pass in.
The second issue is that I need the results to be flatten where the keys are concat rather than nested.
My example input looks like this:
List<Map<String, String>> fakeData = new LinkedList<>();
Map<String, String> data1 = new HashMap<>();
data1.put("ip","10.0.1.0");
data1.put("uid","root");
data1.put("group","admin");
fakeData.add(data1);
Map<String, String> data2 = new HashMap<>();
data2.put("ip","10.0.1.1");
data2.put("uid","tiger");
data2.put("group","user");
fakeData.add(data2);
Map<String, String> data3 = new HashMap<>();
data3.put("ip","10.0.1.1");
data3.put("uid","woods");
data3.put("group","user");
fakeData.add(data3);
The end result have a concat of map keys:
{
"10.0.1.1user": [
{
"uid": "tiger",
"ip": "10.0.1.1",
"group": "user"
},
{
"uid": "woods",
"ip": "10.0.1.1",
"group": "user"
}
],
"10.0.1.0admin": [
"uid": "root",
"ip": "10.0.1.0",
"group": "admin"
]
}
Notice the keys are concat rather than nested maps within maps.
I'm trying to create a groupingby where it can be dynamic without any luck:
fakeData.stream()
.collect(groupingBy(map -> map.get("ip"),
groupingBy(map -> map.get("uuid"),
... nested "n" times)));
This is the interface that I'm trying to implement:
public Map<String, List<Map<String, String>>> doGrouping(List<String> columns,
List<Map<String, String>> data);
Try the following:
public Map<String, List<Map<String, String>>> doGrouping(
List<String> columns,
List<Map<String, String>> data) {
return data.stream()
.collect(Collectors.groupingBy(
elem -> columns.stream()
.map(elem::get)
.collect(Collectors.joining())));
}
First, I streamed the data, which is a list of maps. I immediately collected the stream to a map of lists using Collectors.groupingBy with a key that is calculated for each element of the stream.
Calculating the key was the tricky part. For this, I streamed the given list of columns and I transformed each one of these columns into its corresponding value of the element of the stream. I did this by means of the Stream.map method, passing elem::map as the mapping function. Finally, I collected this inner stream into a single string by using Collectors.joining, which concatenates each element of the stream into a final string in an efficient manner.
Edit: The code above works well if all the elements of columns exist as keys of the map elements in data. To be more secure use the following:
return data.stream()
.collect(Collectors.groupingBy(
elem -> columns.stream()
.map(elem::get)
.filter(Objects::nonNull)
.collect(Collectors.joining())));
This version filters out null elements from the stream, which might occur if some map element does not contain a key specified in the columns list.
Not sure about using streams, but if you prefer plain java way, it is a lot easier.
If I correctly understand your problem here is the method you want to build. You may be required to tweak in a bit to make it faster.
public Map<String, List<Map<String, String>>> doGrouping(List<String> columns, List<Map<String, String>> data) {
Map<String, List<Map<String, String>>> output = new HashMap<>();
for (Map<String, String> map : data) {
String key = "";
for(String column : columns) key += "".equals(key) ? (map.get(column)) : (":" + map.get(column));
output.computeIfAbsent(key, k -> Arrays.asList(map));
}
return output;
}
Test:
doGrouping(Arrays.asList("ip", "group"), fakeData)
>> {10.0.1.1:user=[{uid=tiger, ip=10.0.1.1, group=user}, {uid=woods, ip=10.0.1.1, group=user}], 10.0.1.0:admin=[{uid=root, ip=10.0.1.0, group=admin}]}
doGrouping(Arrays.asList("group"), fakeData)
>> {admin=[{uid=root, ip=10.0.1.0, group=admin}], user=[{uid=tiger, ip=10.0.1.1, group=user}, {uid=woods, ip=10.0.1.1, group=user}]}

A map within a map vs split the key of type String, which will perform faster?

I have a map as Map<String,String>
and the entries are like map.put("c_09.01--x28", "OTH"). In this I use split the key and use the x28 to change it to OTH. So my question is whether I should use split operation or use map within a map and map.put("c_09.01", newMap) where newMap will have map.put("x28", 'OTH'). Which one will give me better performance? sample code where I have used that is
for (Entry<String,String> sheetEntry : this.getSheetCD().getUserDefinedSheetCodeMap().entrySet()) {
String Key = sheet.getKey().split("--")[1];
int sheetIndex = template.getSheetIndex(sheetKey);
if(sheetEntry.getKey().toUpperCase().startsWith(getFileName()){
String newSheetName = sheetEntry.getValue();
template.setSheetName(sheetIndex, newSheetName);
}
}
Please let me know if more information is needed. Regards.
You should use Split operation because if you are using split operation so at the time of iteration the object from map that time you can iterate the value using single forEach loop.
Sample Code
String str[] = "c_09.01--x28".split("--")[1];
Map<String, String> map = new HashMap<>();
map.put(str, "OTH");
for(Map.Entry eMap:map.entrySet()){ //single forEach loop
System.out.println("Key : "+eMap.getKey());
System.out.println("Value : "+eMap.getValue());
}
Output
Key : x28
Value : OTH
If you use map.put("c_09.01", newMap); this one, so you need to iterate two times. Like first you need to iterate newMap using key c_09.01 than again you need to iterate OTH using key x28.
Sample Code
String str[] = "c_09.01--x28".split("--");
Map<String, String> map = new HashMap<>();
map.put(str[1], "OTH");
Map<String, Map> map1 = new HashMap<>();
map1.put(str[0], map);
for(Map.Entry eMap : map1.entrySet()){ //First forEach Loop
System.out.println("Key : "+eMap.getKey()); //getiing key "c_09.01"
Map<String, String> map2 = (Map<String, String>) eMap.getValue(); //getting map and need to be cast because it return object type
for(Map.Entry eMap1 : map2.entrySet()){ // Second forEach loop
System.out.println("Key Using map.put(String, newMAp) : "+eMap1.getKey());
System.out.println("ValueUsing map.put(String, newMAp) : "+eMap1.getValue());
}
}
Output
Key : c_09.01
Key Using map.put(String, newMAp) : x28
ValueUsing map.put(String, newMAp) : OTH
So i guess you should use split operation.

How to print all the values for a key in HashMap in java

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

Categories