Compare two HashMap and multiply map values - java

I have two HashMap and lets say they having the following values:
HashMap1 : <x, 1>, <y, 2>, <z, 3>
HashMap2 : <x,10>, <y, 20>, <z,30>
I want to multiply corresponding values then sum these values like: 1*10 + 2*20 + 3*30. However, I am not sure if I have to use 2 loops or some other iteration. I use one loop but it did no solved the problem:
for (Map.Entry<Character, Integer> entry : map1.entrySet()) {
int sum=0;
if(map2.containsKey(entry.getKey())) {
sum+=entry.getValue() * ...; //it gets map1 values but I also need map2 values to multiply
}
}
How to fix it?

Before Java 8:
int sum = 0;
for (Map.Entry<String, Integer> entry : map1.entrySet()) {
sum += entry.getValue() * map2.getOrDefault(entry.getKey(), 1);
}
Since Java 8:
int sum = map1.entrySet().stream()
.mapToInt(e -> e.getValue() * map2.getOrDefault(e.getKey(), 1)).sum();
Note:
You need to also handle keys which are different between two maps. I assumed that these two maps contains exactly the same keys. Just to keep it simple and clear.

Related

HashMap of HashMap-> output Problems

Having the following HashMap:
HashMap <String, HashMap <Integer, ArrayList <Reservation> >> buffer;
I'm going to output every single value of every single key of the two hashmaps. How can I do?
I have already written this portion of the code:
HashMap map=mod.getAllRecords();
for (Object key: map.keySet()) {
String Date=key.toString();
Object map2=map.get(key);
for(Object Key : ??){//<--------------
}
Easiest way I know is to write three for-loops - first for the key elements themselves which are already strings, second for the integers within the HashMap inside the first HashMap and third for the values inside each array of the second HashMap:
for (String key: map.keySet()) {
System.out.println(key); //prints the strings
HashMap <Integer, ArrayList <Reservation> > map2 = map.get(key);
for(Integer key2 : map2.keySet()){
System.out.println(key2); //prints the integers
for (int i=0;i<map2.get(key2).size();i++) {
System.out.println(map2.get(key2)[i]); //prints everything in the array
}
}
}
Given
Map<String, Map<Integer, List<Reservation>> map = new HashMap<>();
You can print out all the reservations, sans map keys as follows.
map.values().stream()
.flatMap(m->m.values().stream())
.flatMap(List::stream)
.forEach(System.out::println); // prints each reservation
the first stream, streams the inner map (values of the outer map)
the flatMap replaces that stream with the stream of the inner values (the lists)
the last flatMap streams the lists.
The above presumes that the Reservation class has overridden toString
If you want to print out all the keys too, you can do it like this. I indented the output to provide a key/value hierarchy.
map.forEach((k,v)-> {
System.out.println(k);
v.forEach((k1,v1)-> {
System.out.println(" " + k1);
v1.forEach(res->System.out.println(" " + res));
});
});

Filter object permutation in List<List<Entry<String, Double>>> with Java 8

Starting from a list of Entry<String, Double> I just found all the combination with the following method:
public static <T> Stream<List<T>> getCombinationsStream(List<T> list) {
return LongStream.range(1 , 1 << list.size())
.mapToObj(l -> bitMapToList(l, list));
}
Now I want to filter the resulted Lists of Entry to only those who have the sum of all its value
entry.getValue()
equal to a known number.
List<Entry<String, Double>> myList;
double value = 100;
//...
List<List<Entry<String, Double>>> allCombinations = Permutations.getCombinationsStream(myList)
.collect(Collectors.toList());
after that, my goal is to take only the Entry list with the smallest size that has the sum of its value equal to my value (i.e 100)
example:
/*
* allCombinatinos example
*
* [[k1=90.0],[k2=30],[k3=70],
* [k1=90.0, k2=30],[k1=90.0, k3=70],[k2=30, k3=70],
* [k1=90.0, k2=30, k3=70]]
*/
with this lists the expected result will be only one list:
//result
[k2=30, k3=70]
I think that this problem can be handled with .filter() and other stream operation, but I don't know how to figure out.
Here's one way to go about it:
Optional<List<Entry<String, Double>>> min =
getCombinationsStream(myList)
.filter(l -> l.stream()
.mapToDouble(Map.Entry::getValue).sum() == value)
.min(Comparator.comparingInt(List::size));
filters with the said criteria then finds the list of entries with minimum size.

Compare two TreeMap

I have two TreeMap
The first map is:
Map<String, Double> m1 = new TreeMap();
and the second is:
Map<String,double []> m2 = new TreeMap();
I want to search the Key in first map to the second one, and then multiply the value of the first map to the list of second map values (for the similar keys).
After that I will Have an array of type double from the multiplication, then I want to sum the values for each index independent.
For Example:
Map 1:
Apple : 1.0
Cat:2.1
Dog:1.2
Map2:
Apple:{2.0,0.0,4.0}
Dog {1.1,0.0,0.0}
Moon:{0.0,5.0,2.0}
The Result will Be:
Apple{2.0,0.0,4.0}
Dog{1.32,0.0,0.0}
Then the summation :
{3.32,0.0,4.0}
This is my try, I do the search between the two matrixes, then I do the multiplication .
***My question how can I do the summation for each index and how to retrieve a value for spesfic index.
for ( Map.Entry<String,Double> entry : m1.entrySet() ) {
List<Double> myList = new ArrayList<Double>();
if ( m2.containsKey(entry.getKey()) ) {
//if the key is common in map1 and map2, compare the values
double y=entry.getValue();
double j[]=m2.get(entry.getKey());
for (int u=0;u<j.length;u++){
myList.add(j[u]);
}
for (int i=0;i<myList.size();i++){
System.out.println(entry.getKey()+" "+myList.get(i)*y);
}
}}
Given the commutative property of addition, keep the total sum array outside of the loop and for every matched keys, add the current index i of the total sum array to the product of y and j[i].
Let's assume a size N for the array. Then:
double[] finalSum = new double[N];
for ( Map.Entry<String,Double> entry : m1.entrySet() ) {
if ( m2.containsKey(entry.getKey()) ) {
//if the key is common in map1 and map2, compare the values
double y=entry.getValue();
double j[]=m2.get(entry.getKey());
for (int u=0;u<j.length;u++){
finalSum[u] += y * j[u];
}
}
}

How to calculate the sum of values of different hashmaps with the same key?

So I have this hashmap named "hm" which produces the following output(NOTE:
this is just a selection) :
{1=35, 2=52, 3=61, 4=68, 5=68, 6=70, 7=70, 8=70, 9=70, 10=72, 11=72}
{1=35, 2=52, 3=61, 4=68, 5=70, 6=70, 7=70, 8=68, 9=72, 10=72, 11=72}
{1=35, 2=52, 3=61, 4=68, 5=68, 6=70, 7=70, 8=70, 9=72, 10=72, 11=72}
This output was created with the following code(NOTE : the rest of the class code is not shown here) :
private int scores;
HashMap<Integer,Integer> hm = new HashMap<>();
for (int i = 0; i < fileLines.length(); i++) {
char character = fileLines.charAt(i);
this.scores = character;
int position = i +1;
hm.put(position,this.scores);
}
System.out.println(hm);
What I am trying to do is put all these hashmaps together into one hashmap with as value the sum of the values per key. I am familiar with Python's defaultdict, but could not find an equivalent working example. I have searched for an answer and hit those answers below but they do not solve my problem.
How to calculate a value for each key of a HashMap?
what java collection that provides multiple values for the same key
is there a Java equivalent of Python's defaultdict?
The desired output would be :
{1=105, 2=156, 3=183 , 4=204 ,5=206 ..... and so on}
Eventually the average per position(key) has to be calculated but that is a problem I think I can fix on my own when I know how to do the above.
EDIT : The real output is much much bigger ! Think about 100+ of the hashmaps with more than 100 keys.
Try with something like that
public Map<Integer, Integer> combine(List<Map<Integer, Integer>> maps) {
Map<Integer, Integer> result = new HashMap<Integer, Integer>();
for (Map<Integer, Integer> map : maps) {
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
int newValue = entry.getValue();
Integer existingValue = result.get(entry.getKey());
if (existingValue != null) {
newValue = newValue + existingValue;
}
result.put(entry.getKey(), newValue);
}
}
return result;
}
Basically:
Create a new map for the result
Iterate over each map
Take each element and if already present in the result increment the value, if not put it in the map
return the result
newHashMap.put(key1,map1.get(key1)+map2.get(key1)+map3.get(key1));

Find map value with highest number of occurrences

I have a Map<Integer,Integer>
1 10
2 10
3 20
5 20
6 11
7 22
How do I find the maximum repeated value of the map? In this case - that is 10 & 20. Repeated count is 2 on both case.
Don't reinvent the wheel and use the frequency method of the Collections class:
public static int frequency(Collection<?> c, Object o)
If you need to count the occurrences for all values, use a Map and loop cleverly :)
Or put your values in a Set and loop on each element of the set with the frequency method above. HTH
If you fancy a more functional, Java 8 one-liner solution with lambdas, try:
Map<Integer, Long> occurrences =
map.values().stream().collect(Collectors.groupingBy(w -> w, Collectors.counting()));
loop over the hashmap, and count the number of repetitions.
for(Integer value:myMap.values() ){
Integer count = 1;
if(countMap.contains(value)){
count = countMap.get(value);
count++;
}
countMap.put(value, count);
}
then loop over the result map, and find the max(s):
Integer maxValue=0;
for (Map.Entry<Integer, Integer> entry : countMap.entrySet()){
if(entry.getValue => maxValue){
maxValue = entry.getValue;
maxResultList.add(entry.Key);
}
}
Simple solution is you need to write your own put method for getting repeated values
for repeated values
put(String x, int i){
List<Integer> list = map.get(x);
if(list == null){
list = new ArrayList<Integer>();
map.put(x, list);
}
list.add(i);
}
So, in this case, map to a list of [10,10,20,20]
for getting repeated values occurrence
You need be to compare the size of your values list with your values set.
List<T> listOfValues= map.values();
Set<T> listOfSetValues= new HashSet<T>(map.values);
now you need to check size of both collections; if unequal, you have duplicates, to get the max repeated occurrence subtract list from map size.
We can use a number of simple methods to do this.
First, we can define a method that counts elements, and returns a map from the value to its occurrence count:
Map<T, Integer> countAll(Collection<T> c){
return c.stream().collect(groupingByConcurrent(k->k, Collectors.counting()));
}
Then, to filter out all entries having fewer instances than the one with the most, we can do this:
C maxima(Collection<T> c, Comparator<? super T> comp,
Producer<C extends Collection<? super T> p)){
T max = c.stream().max(comp);
return c.stream().filter(t-> (comp.compare(t,max) >= 0)).collect(p);
}
Now we can use them together to get the results we want:
maxima(countAll(yourMap.valueSet()).entrySet(),
Comparator.comparing(e->e.getValue()), HashSet::new);
Note that this would produce a HashSet<Entry<Integer,Integer>> in your case.
Try this simple method:
public String getMapKeyWithHighestValue(HashMap<String, Integer> map) {
String keyWithHighestVal = "";
// getting the maximum value in the Hashmap
int maxValueInMap = (Collections.max(map.values()));
//iterate through the map to get the key that corresponds to the maximum value in the Hashmap
for (Map.Entry<String, Integer> entry : map.entrySet()) { // Iterate through hashmap
if (entry.getValue() == maxValueInMap) {
keyWithHighestVal = entry.getKey(); // this is the key which has the max value
}
}
return keyWithHighestVal;
}

Categories