I am trying to add a Key(String), Value(HashMap) to another HashMap. I somehow keep jumbling up the syntax and logic here. How do I do that? I have a kmap here initialized and then I want to add a key which is a string, and a value which is another HashMap<String, List<Integer>>)
These can be seen in the parameters below:
static HashMap<String, HashMap<String, List<Integer>>> kmap = new HashMap<String, HashMap<String, List<Integer>>>();
public synchronized static void AddMapToList_ofMAP_(HashMap<String, List<Integer>> value, String key) {
if (!kmap.containsKey(key)) {
kmap.put(key, new HashMap<String, List<Integer>>());
}
HashMap<String, List<Integer>> q = kmap.get(key);
q.put(key, value);
}
It's WAY simpler than you're making it seem. You don't need a separate method, just invoke the put(key, value) method on your kmap. Assuming you have a Map<String, List<Integer>> in a variable named value, it's just:
kmap.put(key, value);
That's all. Just one line.
In your parameters you have got a HashMap called value. You are then trying to add that to the HashMap inside the HashMap but the value in that needs to be a List of integers.
Fix:
static HashMap<String, HashMap<String, List<Integer>>> kmap = new HashMap<String, HashMap<String, List<Integer>>>();
public synchronized static void AddMapToList_ofMAP_(
List<Integer> value, String key) {
if (!kmap.containsKey(key)) {
kmap.put(key, new HashMap<String, List<Integer>>());
}
HashMap<String, List<Integer>> q = kmap.get(key);
q.put(key, value);
}
Also, a possible way to make this better is using an Object. I'm not sure how the code and what your putting in but an object could work.
I'm also seeing you get the HashMap by the key but you also put that key in the HashMap (The one inside), surely you could just have 1 HashMap there.
I'm not sure what exactly you are trying to achieve here. Here's what possibly you may want to do. Feel free to write more test cases and optimize the code. However this will give you a based structure to work on.
public class Stackoverflow {
static HashMap<String, HashMap<String, List<Integer>>> kmap = new HashMap<String, HashMap<String, List<Integer>>>();
public synchronized static void addIntegerToKmap(String kmapKey, String intMapKey, Integer value) {
if (!kmap.containsKey(kmapKey)) {
Map<String, List<Integer>> intMap = new HashMap<String, List<Integer>>();
HashMap<String, List<Integer>> stringListHashMap = new HashMap<String, List<Integer>>();
List<Integer> integerList = new ArrayList<Integer>();
integerList.add(value);
stringListHashMap.put(intMapKey, integerList);
kmap.put(kmapKey, stringListHashMap);
}
else {
HashMap<String, List<Integer>> stringListHashMap = kmap.get(kmapKey);
List<Integer> integerList = stringListHashMap.get(intMapKey);
if (integerList != null && !integerList.isEmpty()) {
integerList.add(value);
}
else {
integerList = new ArrayList<Integer>();
integerList.add(value);
stringListHashMap.put(intMapKey, integerList);
}
}
}
public static void main(String args[]) {
addIntegerToKmap("A", "A1", 1);
addIntegerToKmap("A", "A1", 2);
addIntegerToKmap("A", "A2", 12);
addIntegerToKmap("A", "A2", 22);
addIntegerToKmap("B", "B1", 1);
addIntegerToKmap("A", "A1", 3);
}
}
The logic is not clear but maybe you want this
q.put(key, value.get(key));
instead of this:
q.put(key, value);
Related
I have a List<Map<key,value>>. I want to remove it from the list if the key exist in List
For example:
Input: List<Map<a,1>,Map<b,2>,Map<c,3>> (here is a Map) , List<a,d,e>
Explanation: Since, key in map <a,1> exists in the List<a,d,e>, I want to remove Map from the List<Map<a,1>,Map<b,2>,Map<c,3>>
Output: List<Map<b,2>,Map<c,3>>
perhaps you could use java streams api, and do something like this:
public class Mapping {
public static void main(String args[])
{
List<Map<String,Integer>> db = new LinkedList<Map<String,Integer>>();
Map<String,Integer> item = new HashMap<String,Integer>();
item.put("a", 1);
item.put("b", 2);
item.put("c", 3);
db.add(item);
List<String> excludeList = Arrays.asList("a");
List<Map<String,Integer>> newDb = db.stream().map(sample->{
Map<String,Integer> newSample = new HashMap<String,Integer>(sample); //we do not mutate original elements
excludeList.forEach(key->newSample.remove(key));
return newSample;
}).collect(Collectors.toList());
System.out.println(db); //[{a=1, b=2, c=3
System.out.println(newDb); //[{b=2, c=3}]
}
}
in this fashion, you keep both original and new filtered lists
try this, if you want to check the exclude key with list of maps
public static void main(String[] args)
{
List<String> removeList = Arrays.asList("a","d","e");
List<Map<String, Integer>> maps = new ArrayList<>();
//Map1
Map<String, Integer> map1 = new HashMap<>();
map1.put("a", 1);
map1.put("b", 2);
map1.put("c", 3);
maps.add(map1);
//Map2
Map<String, Integer> map2 = new HashMap<>();
map2.put("e", 1);
map2.put("f", 2);
map2.put("g", 3);
maps.add(map2);
for(String string : removeList)
{
for(Map<String, Integer> eachMap: maps)
{
eachMap.remove(string);
}
}
System.out.println(maps);
}
I have a Map with key String and values String and a list of Strings. i want to sort the Map with keys based on the order of values present in the list.
package da.fa;
public class MapSorted {
public static void main(String[] args) {
List<String> efgh = new ArrayList<String>();
efgh.add("ccc");
efgh.add("aaa");
efgh.add("ddd");
efgh.add("aaa");
Map<String, String> abcd = new HashMap<String, String>();
abcd.put("aaa", "1111");
abcd.put("bbb", "1111");
abcd.put("ccc", "1111");
abcd.put("ddd", "1111");
abcd.put("eee", "1111");
}
}
in this, abcd should be sorted by the order of what values are in the list efgh has.
HashMaps are non-sortable, use TreeMap instead :
public static void main(String[] args) {
// define the needed keys
List<String> neededKeys = new ArrayList<String>();
neededKeys.add("ccc");
neededKeys.add("aaa");
neededKeys.add("ddd");
neededKeys.add("aaa");
// build a simple hashmap (unsorted)
Map<String, String> unsortedMap = new HashMap<String, String>();
unsortedMap.put("aaa", "1111");
unsortedMap.put("bbb", "1111");
unsortedMap.put("ccc", "1111");
unsortedMap.put("ddd", "1111");
unsortedMap.put("eee", "1111");
// build a sorted TreeMap and pass only the necessary objects
TreeMap<String, String> sortedMap=new TreeMap<String, String>();
for(String key:unsortedMap.keySet()){
// copy needed keys ONLY to a new sorted map
if (neededKeys.contains(key)){
sortedMap.put(key, unsortedMap.get(key));
}
}
System.out.println(unsortedMap);
System.out.println(sortedMap);
}
If follow suggestion from the aforementioned post how to sort Map values by key in Java, you should write something like this:
Comparator<Foo> comparator = new Comparator<Foo>() {
List<String> final order = .. //Pass your list here;
public int compare(String o1, Stringo2) {
int i1 = order.ingexOf(o1);
int i2 = order.indexOf(o2);
return i1 > i2 ? 1 : (i1 < i1 ? -1 : 0);
}
}
Map<String, String> map = new TreeMap<>(comparator);
map.addAll(abcd);
But what do you need it for? If you want to iterate through this map latter, you can iterate through the list and then fetch value. It will be faster.
And you should remove duplicates from your list:
List<String> efgh = new ArrayList<String>();
...
efgh.add("aaa");
..
efgh.add("aaa");
Otherwise this solution wont work.
I want to be able to convert a List to a HashMap where the key is the elementName and the values is a list of something random (in this case its the Element Name). So in short I want (A->List(A), B->List(B), C-> List(C)). I tried using toMap() and passing it the keyMapper and ValueMapper but I get a compilation error. I would really appreciate if someone can help me out.
Thanks!
public static void main(String[] args) {
// TODO Auto-generated method stub
List<String> list = Arrays.asList("A","B","C","D");
Map<String, List<String>> map = list.stream().map((element)->{
Map<String, List<String>> map = new HashMap<>();
map.put(element, Arrays.asList(element));
return map;
}).collect(??);
}
Function<Map<String, String>, String> key = (map) -> {
return map.keySet().stream().findFirst().get();
};
Function<Map<String, String>, String> value = (map) -> {
return map.values().stream().findFirst().get();
};
=== This worked for me
Thanks for all the help guys! #izstas "they should operate on the elements" helped a lot :). Actually this is what I was looking for to be exact
public static void test2 (){
Function<Entry<String, List<String>>, String> key = (entry) -> {
return entry.getKey();
};
Function<Entry<String, List<String>>, List<String>> value = (entry) -> {
return new ArrayList<String>(entry.getValue());
};
BinaryOperator<List<String>> merge = (old, latest)->{
old.addAll(latest);
return old;
};
Map<String, List<String>> map1 = new HashMap<>();
map1.put("A", Arrays.asList("A1", "A2"));
map1.put("B", Arrays.asList("B1"));
map1.put("D", Arrays.asList("D1"));
Map<String, List<String>> map2 = new HashMap<>();
map2.put("C", Arrays.asList("C1","C2"));
map2.put("D", Arrays.asList("D2"));
Stream<Map<String, List<String>>> stream =Stream.of(map1, map2);
System.out.println(stream.flatMap((map)->{
return map.entrySet().stream();
}).collect(Collectors.toMap(key, value, merge)));
}
You can use the groupingBy method to manage aggregation, for example:
public static void main(String[] args) {
List<String> list = Arrays.asList("A", "B", "C", "D", "A");
Map<String, List<String>> map = list.stream().collect(Collectors.groupingBy(Function.identity()));
}
If you want more flexibility (for example to map the value and return a Set instead of a List) you can always use the groupingBy method with more parameters as specified in javadoc:
Map<City, Set<String>> namesByCity = people.stream().collect(Collectors.groupingBy(Person::getCity, mapping(Person::getLastName, toSet())));
Functions key and value you have defined in your code are not correct because they should operate on the elements of your list, and your elements are not Maps.
The following code works for me:
List<String> list = Arrays.asList("A", "B", "C", "D");
Map<String, List<String>> map = list.stream()
.collect(Collectors.toMap(Function.identity(), Arrays::asList));
First argument to Collectors.toMap defines how to make a key from the list element (leaving it as is), second argument defines how to make a value (making an ArrayList with a single element).
Thanks for all the help guys! #izstas "they should operate on the elements" helped a lot :). Actually this is what I was looking for to be exact
public static void test2 (){
Function<Entry<String, List<String>>, String> key = (entry) -> {
return entry.getKey();
};
Function<Entry<String, List<String>>, List<String>> value = (entry) -> {
return new ArrayList<String>(entry.getValue());
};
BinaryOperator<List<String>> merge = (old, latest)->{
old.addAll(latest);
return old;
};
Map<String, List<String>> map1 = new HashMap<>();
map1.put("A", Arrays.asList("A1", "A2"));
map1.put("B", Arrays.asList("B1"));
map1.put("D", Arrays.asList("D1"));
Map<String, List<String>> map2 = new HashMap<>();
map2.put("C", Arrays.asList("C1","C2"));
map2.put("D", Arrays.asList("D2"));
Stream<Map<String, List<String>>> stream =Stream.of(map1, map2);
System.out.println(stream.flatMap((map)->{
return map.entrySet().stream();
}).collect(Collectors.toMap(key, value, merge)));
}
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)
Given the class:
public class CategoryValuePair
{
String category;
String value;
}
And a method:
public Map<String,List<String>> convert(CategoryValuePair[] values);
Given that in values we can receive many entries with the same category, I want to convert these into a Map grouped on category.
Is there a quick / efficient way to perform this conversion?
As far as I know there is not easier way than iterating on values, and then putting the values in the map (like some predefined method).
Map<String, List<String>> map = new HashMap<String, List<String>>();
if (values != null) {
for (CategoryValuePair cvp : values) {
List<String> vals = map.get(cvp.category);
if (vals == null) {
vals = new ArrayList<String>();
map.put(cvp.category, vals);
}
vals.add(cvp.value);
}
}
I changed the map values from String[] to List<String> since it seems easier to me to use that so you don't have to hassle with array resizing.
To make it in fewer lines of code, use Google Collections:
public Map<String, Collection<String>> convert(CategoryValuePair[] values) {
Multimap<String, String> mmap = ArrayListMultimap.create();
for (CategoryValuePair value : values) {
mmap.put(value.category, value.value);
}
return mmap.asMap();
}
If you don't want to allow duplicate values, replace ArrayListMultimap with HashMultimap.
With lambdaj you just need one line of code to achieve that result as it follows:
group(values, by(on(CategoryValuePair.class).getCategory()));
Just for the sake of implementation... The method returns Map and also checks for duplicates in the arrays... though performance wise its heavy ...
public Map<String,String[]> convert(CategoryValuePair[] values)
{
Map<String, String[]> map = new HashMap<String, String[]>();
for (int i = 0; i < values.length; i++) {
if(map.containsKey(values[i].category)){
Set<String> set = new HashSet<String>(Arrays.asList(map.get(values[i].category)));
set.add(values[i].value);
map.put(values[i].category, set.toArray(new String[set.size()]));
}else {
map.put(values[i].category, new String[]{values[i].value});
}
}
return map;
}