ConcurrentHashMap contains Map Objects - java

If ConcurrentHashMap contains Map then, is Internal Values Map also behave Concurrent or not?
The following is my map object
ConcurrentHashMap<String, Map<String, Map<String, String>>> applicationDataMap =
new ConcurrentHashMap<>();

The variable declaration here only uses the Map interface. You can add any Map to this, whether concurrent or not. If you require all of the contained maps to be concurrent, you must declare them as such:
ConcurrentHashMap<String, ConcurrentHashMap<String, ConcurrentHashMap<String, String>>> applicationDataMap = new ConcurrentHashMap<>();

You could put any type of Map in applicationDataMap.
E.g.:
Map<String, String> innerInnerMap = new TreeMap<>();
Map<String, Map<String, String>> innerMap = new HashMap<>();
innerMap.put("innerKey", innerInnerMap);
applicationDataMap.put("key", innerMap);
There's nothing protecting these inner maps from being concurrently accessed by more than one thread. If you want to ensure their validity, you'd have to handle it explicitly.

Related

Map of Map iteration

Im storing 2 map with different structure in single map like below,
Map<String, List<String>> colMap = new HashMap<String, List<String>>();
Map<String, String> appMap = new HashMap<String, String>();
// colMap assigning some values
// appMap assigning some values
Map<String, Map> mainMap = new HashMap<String, Map>();
mainMap.put("appMap", appMap);
mainMap.put("colMap", colMap);
I want to get map one by one and iterate the map.
If I try get map like below, getting error,
.......
Map colMap = map.get("colMap");
for(Entry<String, List<String>> entry : colMap.entrySet())
Error: Type mismatch: cannot convert from element type Object to Map.Entry<String,List<String>>
Why not just create a simple container POJO class (or record in Java 16+) for the two maps instead of mainMap and keep the relevant type-safety which to do it Java-way?
public class MapPojo {
private final Map<String, List<String>> colMap;
private final Map<String, String> appMap;
public MapPojo(Map<String, List<String>> colMap, Map<String, String> appMap) {
this.colMap = colMap;
this.appMap = appMap;
}
// getters, etc.
}
MapPojo mainMap = new MapPojo(colMap, appMap);
Error you are getting because when you are doing map.get operation your reference is Just Map without any Generics which will treated as Object class's reference. You should use generics like below and it will work -
Map<String, List<String>> colMap = map.get("colMap");
for(Entry<String, List<String>> entry : colMap.entrySet())

How to correctly define a multidimensional generalized Collection in Java?

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>

Define a recursive definition of a HashMap using generics

Is there a way to define a HashMap that has another HashMap as the value without warning?
I mean if I use generics I would have to define:
HashMap<Integer, HashMap<Integer, HashMap<Integer, HashMap<Integer,HashMap etc>> map = new HashMap<>();
Is the correct/only way to do it via the followin?
HashMap<Integer, HashMap> map = new HashMap<Integer, HashMap>();
Update based on comments:
I am just reviewing generics and I was under the impression that it is not uncommon to have a hashmap as a value of another hashmap.
Update based on #JimGarrison comment:
Using a hash of hashes is a very common structure in other languages so I am surprised that I need to actually give some specific use case in order for my question to make sense. If I need to give a real example that this could be used, one would be to e.g. navigate through some hierarchical structure. So we could "mimic" a tree.
You might find F-bound types useful, at least from a theoretical point of view. In your case, this might be:
class FBoundedMap<K> extends HashMap<K, FBoundedMap<K>> {
}
Then you could use it this way:
FBoundedMap<Integer> map = new FBoundedMap<>();
FBoundedMap<Integer> inner1 = new FBoundedMap<>();
map.put(1, inner1);
FBoundedMap<Integer> inner2 = new FBoundedMap<>();
map.put(2, inner2);
FBoundedMap<Integer> innerMost1 = new FBoundedMap<>();
inner1.put(11, innerMost1);
FBoundedMap<Integer> innerMost2 = new FBoundedMap<>();
inner2.put(22, innerMost2);
System.out.println(map); // {1={11={}}, 2={22={}}}
You could only store empty maps at the end, and maps of maps in the middle, so the only practical use I see to this is to store data in the keys (in this case these would be Integers) and use the values to keep references to children nodes of a tree structure.
Another way would be to let the values be of any type, including HashMap. This way, you could store maps as values of other maps. In this case, you'd need to declare your maps as:
Map<Integer, Object> map = new HashMap<>();
Map<Integer, Object> inner1 = new HashMap<>();
map.put(1, inner1);
Map<Integer, Object> inner2 = new HashMap<>();
map.put(2, inner2);
Map<Integer, Object> innerMost1 = new HashMap<>();
inner1.put(11, innerMost1);
Map<Integer, Object> innerMost2 = new HashMap<>();
inner2.put(22, innerMost2);
System.out.println(map); // {1={11={}}, 2={22={}}}
Of course, if you need to get a value, you'd need to cast:
Map<Integer, Object> value = (Map<Integer, Object>) map.get(1);
System.out.println(value); // {11={}}

Map of maps - putting value to inner map

I have map of maps
Map<String, Map<String,Integer>> outerMap = new HashMap<String, Map<String, Integer>>();
and I want to put some values to inner map. Is that correct way? Or it can be done better?
class SampleMap {
Map<String, Map<String, Integer>> outerMap = new HashMap<String, Map<String, Integer>>();
public void add(String outerKey, String innerKey, Integer value) {
Map<String, Integer> tempMap = new HashMap<String, Integer>();
if (outerMap.size() > 0)
tempMap = outerMap.get(outerKey);
tempMap.put(innerKey, value);
outerMap.put(key, tempMap);
}
}
You can improve the code by avoiding the creation of a new inner map eagerly, until the point when you know that you must create it.
In addition, if you know that the inner map instance came from the outer map, you don't have to spend time putting it back where it came from.
public void add(String outerKey, String innerKey, Integer value) {
Map<String, Integer> tempMap
if (outerMap.containsKey(outerKey)) {
tempMap = outerMap.get(outerKey);
} else {
tempMap = new HashMap<String, Integer>();
outerMap.put(outerKey, tempMap);
}
tempMap.put(innerKey, value);
}
Technically there is nothing wrong in your code (except a minor improvement suggested by dasblinkenlight), but is map of maps what you really need?
If you want to read/write values by two keys, probably it's better to create map from pair of two keys (MultiKey or Pair implementation can be used) or another data structure (see this comment for details https://stackoverflow.com/a/3093993/554281)

The way to instantiate map<String, List<String>> in Java

I would like to instantiate Map<String, List<String>> in Java,
I tried
Map<String, List<String>> foo = new <String, List<String>>();
and
Map<String, List<String>> foo = new <String, ArrayList<String>>();
None of them work. Does any one know how to instantiate this map in Java?
new HashMap<String, List<String>>();
or as gparyani commented:
new HashMap<>(); // type inference
Note: each entry needs to be given an instantiated List as a value. You cannot get("myKey").add("some_string_for_this_key"); the very first time you get() a List from it.
So, fetch a List, check if it's null.
If it's null, make a new list, add the string to it, put the List back.
If it's anything but null, add to it, or do what you want.
You forgot to mention the class. Map here is the reference type and is an Interface. HashMap on the other side of equals specifies the actual type of the Object created and assigned to the reference foo.
Map<String, List<String>> foo = new HashMap<String, List<String>>();
The actual type specified (HashMap here) must be assignable to the reference type (Map here) i.e. if the type of reference is an Interface, the Object's type must implement it. And, if the type of the reference is a Class, the Object's type must either be the same class or its subtype i.e. it extends from it.
From Java 7 onwards, you can use a shorthand like
Map<String, List<String>> foo = new HashMap<>();
Your second way of instantiation is not recommended. Stick to using List which is an Interface.
// Don't bind your Map to ArrayList
new TreeMap<String, ArrayList<String>>();
// Use List interface type instead
new TreeMap<String, List<String>>();
Map is an interface. You have to tell Java which concrete Map class you want to instantiate.
Map<String, List<String>> foo = new HashMap<String, List<String>>();
or
Map<String, List<String>> foo = new TreeMap<String, List<String>>();
etc.

Categories

Resources