I've map of key value pairs with each value being a map of key value pairs.
Something like
Map<String, Map<String, Integer> outMap = new HashMap<>();
Map<String, Integer> inMap = new HashMap<>();
inMap.put("i11", 111);
inMap.put("i21", 121);
outMap.put("o1", inMap);
How would I handle the entry where I can create/update at both levels of the map using java 8 ?
Input would be outer key/inner key and value. So we should we able to add a new entry is it doesn't exist in outer map. If the entry exists in outer map then insert the new entry in inner map if it doesn't exist else update the inner map with new value.
What you want to achieve can be done with this single line of code:
outerMap.computeIfAbsent(outerKey, k -> new HashMap<>()).put(innerKey, value)
But without these methods, you can achieve the same with just get() and put():
Map<String, Integer> innerMap = outerMap.get(outerKey);
if (innerMap == null) {
innerMap = new HashMap<>();
outerMap.put(outerKey, innerMap);
}
innerMap.put(innerKey, value);
HOW TO UPDATE THE SINGLE-VALUE AND MULTIPLE VALUES AT THE SAME TIME SIMULTANEOUSLY IN TWO MAPS
NTOE:
givenMap.computIfAbsent(k,Funtion) -> if key in given map is null or absent, then compute the value using funtion and add into the given map
Map<String, Map<String, Integer>> outMap = new HashMap<>();
Map<String, Integer> inMap = new HashMap<>();
inMap.put("i11", 111);
inMap.put("i21", 121);
outMap.put("o1", inMap);
System.out.println(outMap.toString());
System.out.println(inMap.toString());
OUTPUT BEFORE UPDATING:
{o1={i11=111, i21=121}}
{i11=111, i21=121}
//If you want to add one value in the inner hashmap you created:
outMap.computeIfAbsent("newHashMapKey",k -> new HashMap<>()).put("Arpan",2345);
// if you want to add more than 1 value at a time in the inner hashmap
outMap.computeIfAbsent("newHashMapKey2",k -> new HashMap<>()).putAll(new HashMap<String, Integer>(){{
put("One", 1);
put("Two", 2);
put("Three", 3);
}});
System.out.println(outMap.toString());
System.out.println(inMap.toString());
OUTPUT AFTER UPDATING BOTH MAPS AT THE SAME TIME
{o1={i11=111, i21=121}, newHashMapKey2={Two=2, Three=3, One=1}, newHashMapKey={Arpan=2345}}
{i11=111, i21=121}
Related
I have the following structure
HashMap<String, HashMap<String, String>> h = new HashMap<>();
HashMap<String, String>> h1 = new HashMap<>();
h1.put("key10", "value10")
h1.put("key11", "value11")
h1.put("date", "2018-10-18T00:00:57.907Z")
h.put("1#100", h1)
HashMap<String, String>> h2 = new HashMap<>();
h2.put("key20", "value20")
h2.put("key21", "value21")
h2.put("date", "2023-02-03T10:00:00.907Z")
h.put("2#000", h2)
Imagine I have many entries like the examples above.
In certain moment (scheduler) i have this requirement:
check all nested hash maps (for each/stream)
see if date condition is true
find parent key and delete from main hash map
In this exemple the final hash map will be
h2.put("key20", "value20")
h2.put("key21", "value21")
h2.put("date", "2023-02-03T10:00:00.907Z")
h.put("2#000", h2)
h2 => {key20 => value20, key21 => value21, date => 2023-02-03T10:00:00.907Z}
i have this code right now
h.forEach((k,v) -> {
v.entrySet()
.stream()
.filter(e -> e.getKey().equals("date"))
.filter(t -> Timestamp.from(Instant.now()).getTime() - Timestamp.valueOf(t.getValue()).getTime() > milisDiff)
//need now to access parent and delete with by k key
Can do in one step (lambda) or i need to have extra structure to collect parent keys and after proceed to delete within for each ?
This may do what you want. Just filter out bad elements and assign to the same map.
HashMap<String, HashMap<String, String>> h = new HashMap<>();
HashMap<String, String> h1 = new HashMap<>();
h1.put("key10", "value10");
h1.put("key11", "value11");
h1.put("date", "2018-10-18T00:00:57.907Z");
h.put("1#100", h1);
HashMap<String, String> h2 = new HashMap<>();
h2.put("key20", "value20");
h2.put("key21", "value21");
h2.put("date", "2023-02-04T10:00:00.907Z");
h.put("2#000", h2);
// any instant after `now` will pass the filter and be put in the map
Predicate<String> check = str -> Instant.parse(str)
.isAfter(Instant.now());
h = h.entrySet().stream()
.filter(e -> check.test(e.getValue().get("date")))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue,
(a,b)->a,
HashMap::new));
h.values().forEach(m -> {
m.entrySet().forEach(System.out::println);
});
prints
date=2023-02-04T10:00:00.907Z
key21=value21
key20=value20
My predicate simply deleted the date if it expired. Yours was a tighter threshold.
Updated
Here is another option in case building a new map takes too long. It uses an iterator to run thru the loop and modify the existing map by removing Maps with old dates.
Iterator<Entry<String,Map<String,String>>> it = h.entrySet().iterator();
while (it.hasNext()) {
Entry<String,Map<String, String>> e = it.next();
if (!check.test(e.getValue().get("date"))) {
it.remove();
}
}
I need to make a third HashMap based off the values from the PeopleAndNumbers and PeopleAndGroups hashmaps. But the third HashMap would only have the 3 groups as keys and the total amounts from the people in that group as values.
(Also worth noting that the keys in the first both maps are the same.)
Here are the contents of the first two maps:
PeopleAndNumbers: {p1=1, p2=3, p3=2, p4=3, p5=1, p6=2}
PeopleAndGroups: {p1=GroupA, p2=GroupB, p3=GroupC, p4=GroupB, p5=GroupC, p6=GroupA}
I need to make a third HashMap that'd print out like this:
CombineMap: {GroupA=3, GroupB=6, GroupC=3}
Here is what the code looks like so far:
import java.util.HashMap;
public class HashmapTest {
public static void main(String[] args) {
HashMap<String, Integer> PeopleAndNumbers = new HashMap<String, Integer>();
HashMap<String, String> PeopleAndGroups = new HashMap<String, String>();
PeopleAndNumbers.put("p1", 1);
PeopleAndNumbers.put("p2", 3);
PeopleAndNumbers.put("p3", 2);
PeopleAndNumbers.put("p4", 3);
PeopleAndNumbers.put("p5", 1);
PeopleAndNumbers.put("p6", 2);
PeopleAndGroups.put("p1","GroupA");
PeopleAndGroups.put("p2","GroupB");
PeopleAndGroups.put("p3","GroupC");
PeopleAndGroups.put("p4","GroupB");
PeopleAndGroups.put("p5","GroupC");
PeopleAndGroups.put("p6","GroupA");
System.out.println(PeopleAndNumbers);
System.out.println(PeopleAndGroups);
HashMap<String, Integer> CombineMap = new HashMap<String, Integer>();
//Insert method to do this here, How would I go about this?
System.out.println("Expected Output for CombineMap should be");
System.out.println("{GroupA=3, GroupB=6, GroupC=3}");
System.out.println(CombineMap);
}
}
If I understand you correctly, you want to sum Numbers by Group, using the common keys to join them. If so, you can do it pretty easily with streams:
Map<String, Integer> combined = PeopleAndGroups.entrySet()
.stream()
.collect(Collectors.groupingBy(e -> e.getValue(),
Collectors.summingInt(e -> PeopleAndNumbers.get(e.getKey()))));
Or you can iterate and merge entries into your destination map:
Map<String, Integer> combined = new HashMap<>();
PeopleAndGroups.forEach((k, v) ->
combined.merge(v, PeopleAndNumbers.get(k), Integer::sum));
To achieve that you need to iterate over the entries of the PeopleAndGroups map and do the following for each entry:
check if the combinedMap has a key equal to the value of the current entry
If the key doesn't exist put the key with value 0: combinedMap.put(entry.getValue(), 0)
Get the value of the entry's key from the PeopleAndNumbers and let's call it N: int N = PeopleAndNumbers.get(entry.getKey())
add N to the old value of your result map:
combinedMap.put(entry.getValue(), combinedMap.get(entry.getValue()) + N)
Map<String, String> hash_map = new LinkedHashMap<String, String>();
Map<String, String> new_hash_map = new LinkedHashMap<String, String>();
hash_map.put("AA", "Geeks");
hash_map.put("BB", "4");
hash_map.put("CC", "Geeks");
hash_map.put("DD", "Welcomes");
hash_map.put("EE", "You");
new_hash_map.put("BB", "4");
new_hash_map.put("EE", "You");
new_hash_map.put("FF", "Me");
hash_map contains some keys and values, new_hash_map also conatins some keys and values.
My requirement is to compare the new_hash_map with hash_map and return valid key-value pair map of new_hash_map
You can use stream with Java 8 to get the intersection between maps in this way:
Map<String, String> intersection = hash_map.entrySet().stream()
.filter(map -> (new_hash_map.containsKey(map.getKey())
&& new_hash_map.get(map.getKey()).equals(map.getValue())))
.collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue()));
This code uses filter to get values into map where key and value are the same. I.e. the intersection between two maps.
And value of intersection variable is: {EE=You, BB=4}.
Also I've added new_hash_map.put("CC", "Me"); to ensure CC key is not output.
For instance if I have a map with integer and strings:
Map<Integer, String> myMap = new HashMap<Integer, String>();
This map would contain key values of Integers and values of names.
What I am trying to do is make a new map, that copies all the values (names) from theMap and makes them the keys for the new map. Now the tricky part I can't get, is that I want the values of the new map to be the numbers, but if there are multiple numbers that correspond to the same name I want them to be held in an Set.
Example of new map:
Map<String, Set<Integer>> returnMap = new TreeMap<String, Set<Integer>>();
So if "John" corresponds to 1,2,3,4. I would like the new map to contain a key of "John" with a Set containing 1,2,3,4
Google's Guava library has a nice Multimap class which maps keys to multiple values. If you use it, you can take advantage of a host of helper methods:
SetMultimap<String, Integer> returnMap =
Multimaps.invertFrom(Multimaps.forMap(myMap), TreeMultimap.create());
It's not that tricky :)
Map<Integer, String> map = ... //Your map
Map<String, Set<Integer>> reverseMap = new TreeMap<String, Set<Integer>>();
for(Map.Entry<Integer, String> entry : map.entrySet()) {
Integer key = entry.getKey();
String value = entry.getValue();
Set<Integer> set;
if(reverseMap.containsKey(value)) {
set = reverseMap.get(value);
set.add(key);
} else {
set = new HashSet<Integer>();
set.add(key);
reverseMap.put(value, set);
}
}
I have the following HashMap where the key is String and value is represented by a HashMap.
HashMap<String, HashMap<String, Integer> outerMap = new HashMap<String,HashMap<String, Integer>();
HashMap<String, Integer> innerMap = new HashMap<String, Integer>();
innerMap.put("Amount", 2000);
outerMap.put("TutionFee", innerMap);
Now I want to update the value of Amount key. How can I update the value of Amount key?
This should work:
outerMap.get("TutionFee").put("Amount", newValue);
Suppose new value to update is 1000, then outerMap.get("TutionFee").put("Amount", 1000);