I have the following data structure:
Map<String,Map<String,String>>
I'd like to extract its value (which itself is another string Map) from this complex Map object. I am currently doing it as such:
Map<String, Map<String, String>> map = getStructure(data,format);
Map<String,String> newMap = new LinkedHashMap<String, String>();
for(Entry<String, Map<String,String>> entry : map.entrySet()) {
for (Entry<String, String> value : entry.getValue().entrySet()) {
newMap.put(value.getKey(),value.getValue());
}
}
The above implementation gives me a new Map object with repeating key-value pairs due to the outer foreach loop, it is iterating through. Seems like I'm missing something.
How can I extract the inner Map object from the complex Map object?
Edit:
Addressing AlexWien's comment
Original Data Structure:
The reasoning behind the original data structure is to store a single value for a pair of IDs (ID1 and ID2). ID1 and ID2 may be different. So it is structured as:
Map<String,Map<String,String>> ===> <someValue, <ID1,ID2>>
What I am trying to achieve is to get the entire list of the id pairs (ID1 and ID2) for every someValue. So I can store them in a database to keep track of aeronautical information.
Having an map of maps:
Map<String, Map<String, String>> map
you get the inner map simply by calling get
String key = ...; // TODO
Map<String, String> innerMap = map.get(key);
Update to your edit:
It further seems you need something like a map of pairs:
Map<String, Pair<String, String>> mapOfPairs.
Unfortuneatly java has no Pair class.
So write one yourself:
public class Pair {
String id1;
String id2;
}
and have a
Map<String, Pair> mapOfPairs;
Related
I have a map object whose value is:
{Name={
Id=9999,
status=OK,
Idn={
source=TEST,
value=123,
TS=2018-11-14T18:10:33.998Z
}
}}
I have to remove the value=123 part from it so that my final Map looks like:
{Name={
Id=9999,
status=OK,
Idn={
source=TEST,
TS=2018-11-14T18:10:33.998Z
}
}}
the .remove(key) part would work on "Name" tag but I am unable to reach the nested Name.Idn.value and remove it.
Edited code:
My map is populated from mongoTemplate.findOne()
Map<String, Map<String, Object>> response
Query query = new Query();
Criteria criteria = Criteria.where("Name.Idn.value").is(123);
query.addCriteria(criteria).fields().exclude("_id");
response = mongoTemplate().findOne(query, Map.class, "dummy_col");
From response, while sending response back, the Name.Idn.value is to be removed.
I'd guess you have a Map<String, Object> map to be able to hold such different types as values, so you need to case first value as Map<String, Map> to be able to continue your path
((Map<String, Map<String, Object>>) map.get("Name")).get("idn").remove("source");
In fact yo have a Map<String, Map<String, Object>> map, so you know the first get() will return a Map, this is the second one that you need to cast
((Map<String, Object>) map.get("Name").get("idn")).remove("source");
You seem to have 3 levels of nested maps.
The value of name is a map, which has a key Idn with value that is also a map.
So, you would need a code that would look like this:
Map<String, Map<>> top = { ... };
Map<String, Map<>> name = top.get("Name");
Map<String, String> idn = name.get("Idn");
idn.remove("value");
You could also do it in one line like this:
Map <String, Map> top = { ... };
top.get("Name").get("Idn").remove("value");
For example, I want to create a map that is a map of a map of a map. So I have declared the map as so. From a resultset I want to create a JSON object.
Map<String, Map<String, Map<String, String>>> data = new LinkedHashMap<String, Map<String, Map<String, String>>>();
I could define as
Map<String, Object> map = new LinkedHashMap<String, Object>();
however I need to put items one at a time so I get the map I want and put it in. Then the same the following iterations so I would have to cast the object to the map which leaves unchecked warnings.
Is there a better way of declaration of this type of Collection?
You can use a Google Guava MultiMap, but really you're better off creating a new Object and referencing the entire collection of data from the single key.
public class MyObjectData {
private String string1;
private Map<String, String> map;
// Getters and setters
}
Then your map becomes Map<String, MyObjectData>
Here is what I'm trying to do.
Map<String, List<Address>> mapObj = someService.getSomeAddress();
Using above call I'm getting mapObj of type Map<String, List<Address>>
And I want to send mapObj as a parameter in a another method (that I cannot change) as a LinkedHashMap<String, List<LinkedHashMap>> which does some further processing.
Is there any way that I can solve this problem without affecting data inside mapObj?
You will need to perform a couple of conversion steps.
Convert all Address objects to LinkedHashMap objects.
Put all Map entries into a LinkedHashMap object.
For 1st one, you can write a utility method some where that can do this conversion. For example,
public static List<LinkedHashMap> addresstoMap(List<Address> addresses)
{
List<LinkedHashMap> list = new ArrayList<>();
for(Address a: addresses){
LinkedHashMap map = new LinkedHashMap();
// Add address fields to map here
list.add(map);
}
return list;
}
Then, for the 2nd step, you can do this:
LinkedHashMap<String, List<LinkedHashMap>> map = new LinkedHashMap<?,?>();
iterate through the entry sets of mapObj and put them into the above map object.
for (Map.Entry<String, List<Address>> e : m.entrySet()) {
map.put(e.getKey(), addresstoMap(e.getValue()));
}
The final map object above will contain the correct representation in the LinkedHashMap<String, List<LinkedHashMap>> datatype.
Hope this helps!
I'm trying to retrieve values from a nested hashmap depending on user selection. I'm having trouble getting the values from the nested Hashmap.
I've created the HashMap like this
private Map<String, Map<String, String>> contentTypesMap = new HashMap<String, Map<String, String>>();
If the user selects MDX i want to go to the nested HashMap and get the two string values in the 2nd hashmap.
contentTypesMap.put("MDX", new HashMap<String,String>()).put("HELLO1", "FOO");
And this my function for where to use hashmap,
public void getDatabaseSelectionValues (){
resourceType = (String) FileUtilityScreen.contentTypes.getSelectedItem();
sqlTableName = contentTypesMap.get(resourceType).get(key);
languageSelected = FileUtilityScreen.languagesFromDataBase.get(
FileUtilityScreen.languageDropDown.getSelectedItem());
}
with your exemple, if the selection is "MDX", you get your second map by doing
HashMap<String,String> selection = contentTypesMap.get("MDX")
then you can use entrySet() method to retrieve all entries of your map and iterate over entries.
See the documentation from Map.put(K key, V value)
#return the previous value associated with key, or
null if there was no mapping for key
So calling contentTypesMap.put("MDX", new HashMap<String,String>()) will always return the value that is not in the contentTypesMap map anymore.
Solution :
HashMap<String, String> map = contentTypesMap.get("MDX");
if (map == null) {
map = new HashMap<>();
contentTypesMap.put("MDX", map);
}
map.put("HELLO1", "FOO");
Or you can use guava Multimap instead.
Is the HELLO1 and FOO meant to be the value for MDX?
You are not putting it correct. Try this:
Map<String, String> value = new HashMap<String, String>();
value.put("HELLO1", "FOO");
contentTypesMap.put("MDX", value);
I'd also consider wrapping this outer map in its own object as it may get complex.
What I meant by a wrapper class in my comment above was something along these lines, to make it more readable. I'm assuming the key in the outer map is the table name, and in the inner map is the column name and data type for that column.
public class DatabaseTables {
private Map<String, Map<String, String>> dbTables = new HashMap<String, Map<String, String>>();
public void addColumn(String tableName, String column, String type){
Map<String, String> columns = dbTables.get(tableName);
if(dbTables.get(tableName) == null) {
columns = new HashMap<String, String>();
}
columns.put(column, type);
dbTables.put(tableName, columns);
}
public Map<String,String> getColumnsForTable(String tableName){
return dbTables.get(tableName);
}
}
That still feels ugly though. I think a better solution than this, would be to have a class called Table, with a string property for the table name, and a map for its columns and data types.
And then, elsewhere, you could have a list or a set of type Table.
Edit: Or, in Table.java, rather than a map for the columns, you could have a list or set of type Column. And then create a column class with two fields, one for the column name and the other for the type.
I have a problem saving and accessing data from a map which is inside another map.
Map<String, Integer> Mapname=new LinkedHashMap<String, Integer>();
Mapname.put("hello",2);
Mapname.put("bye",3);
Map<String, Map<String,Integer> OutsiderMap
= new LinkedHashMap<String, Map<String, Integer>>();
String s="name";
OutsiderMap.put(s,Mapname);
for (Map.Entry<String, Map<String,Integer>> entry : OutsiderMap.entrySet())
{
Map<String,Integer> innermap;
innermap=entry.getValue();
for (Map.Entry<String, Integer> entry2 : innermap.entrySet())
{
}
}
Output should be:
Should print the Outsider map not the inner map
Output now:
s={};
My output right now is the name of the string s={}. So my oustider map is empty.
Can you please tell me what is wrong?
Its working with Eclipse Luna, just add the following statement in inner for loop System.out.println(entry2); to access Map elements stored in the an another Map.