programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
• Campbell Ritchie
• Jeanne Boyarsky
• Ron McLeod
• Paul Clapham
• Liutauras Vilda
Sheriffs:
• paul wheaton
• Rob Spoor
• Devaka Cooray
Saloon Keepers:
• Stephan van Hulst
• Tim Holloway
• Carey Brown
• Frits Walraven
• Tim Moores
Bartenders:
• Mikalai Zaikin

# Compare values in HashMap - Efficient Problem Sovling

Ranch Hand
Posts: 182
1
• Number of slices to send:
Optional 'thank-you' note:
Hello,

I am looking for the more efficient way to solve the following problem:

I have two HashMaps. Each Map has as a key a unique date and as a value a String. For Example:
(Date format: dd/mm/yyyy)
I have two HashMaps and an ArrayList where in the ArrayList I store the final result.

HashMap1
Key                    Value
29/05/2017         Alice
15/03/2017         Alice
29/06/2017         Alice
20/04/2017         Bob
13/02/2017         George

HashMap2
Key                             Value
27/05/2017         Alice
19/06/2017         Alice
15/06/2017         George

If a value exists only on HashMap1 then add it on the result ArrayList.
If a value exists only on HashMap2 do nothing.

If a value that exists on HasMap1, exists on HashMap2 as well then compare dates(keys) of all values found on both HashMaps. If the maximum date belongs to the value of HashMap1 then add the value on the result ArrayList. If the maximum date belongs to value of HashMap2 then do nothing.

In the example above to the results Arraylist should be added : Bob and Alice (because of date : 29/06/2017). George , even though belongs to both HashMaps, should not be added because the maximum date is of value of HashMap2.

Do you know which is the most efficient way to achieve this?
I thought to iterate through the all the values of HashMap1 and do a HashMap2.containsValue(valueOfHashMap1) to check first if the HashMap2 contains the value of HashMap1.
If true, then iterate again though both HashMaps and store in an ArrayList all the keys and then find the maximum key(date)?

I don't really like this solution. Maybe it is best to use something else rather than HashMap?

Any help is appreciated,
Thanks
Ioanna

Saloon Keeper
Posts: 15445
362
• 1
• Number of slices to send:
Optional 'thank-you' note:
I think the easiest way to do this is to first invert both maps, and discard all the entries that don't contain the greatest dates. It looks like this:

Your two maps will then look like this:

KeyValue
Alice29/06/2017
Bob20/04/2017
George13/02/2017

KeyValue
Alice19/06/2017
George15/06/2017

Now, you just remove entries from the first map if the second map contains an entry with the same name, but a greater date. Use map.entrySet().removeIf() for this task.

Ioanna Katsanou
Ranch Hand
Posts: 182
1
• 1
• Number of slices to send:
Optional 'thank-you' note:
Hey Stephan,

So I implemented the invertAndKeepEntriesWithGreatestDate method as following. Seems to be working fine. What's your opinion on this?

Ioanna Katsanou
Ranch Hand
Posts: 182
1
• Number of slices to send:
Optional 'thank-you' note:
Also, for the second step:

Now, you just remove entries from the first map if the second map contains an entry with the same name, but a greater date. Use map.entrySet().removeIf() for this task.

I did the following implementation. Is that what you meant??

Thanks again !! ioanna

Stephan van Hulst
Saloon Keeper
Posts: 15445
362
• Number of slices to send:
Optional 'thank-you' note:
A few things:

Don't use java.util.Date. Use java.time.LocalDate instead.

Using types in variable names is bad practice. Rather, describe what the variables mean. Call your variable inverted, instead of myNewHashMap.

You're performing a lookup twice for each entry: containsKey() and get(). In general, you would just use get() and check if the result is not null. However, see the next comment for an even better solution.

It's pointless to remove a entry from a map if you're immediately going to add an entry with the same key. Instead, just use the put() method to overwrite the existing value. However, in this particular case you can replace your containsKey(), get(), remove() and put() calls with a single call to merge():

I prefer to use collectors for a more declarative approach though:

Stephan van Hulst
Saloon Keeper
Posts: 15445
362
• Number of slices to send:
Optional 'thank-you' note:

Ioanna Katsanou wrote:I did the following implementation. Is that what you meant??

This solution has the same problem as your solution for inverting the map: You're performing a containsKey(), get() and remove() all in tandem. Instead, you can solve this with a single call to merge():

Ioanna Katsanou
Ranch Hand
Posts: 182
1
• Number of slices to send:
Optional 'thank-you' note:
Hello Stephan,

Thank you again so much.
Unfortunately, I am using Java SE7 , and not SE8, therefore I cannot use the merge method and lambda expressions.
But I made all the other changes:
• Replaced the name of the variable myNewHashMap with inverted.
• Used java.time.LocalDate
• You're performing a lookup twice for each entry: containsKey() and get(). In general, you would just use get() and check if the result is not null. However, see the next comment for an even better solution.
• Replaced contains with the get method, and removed the “remove” method.

Stephan van Hulst
Saloon Keeper
Posts: 15445
362
• 1
• Number of slices to send:
Optional 'thank-you' note:
Why are you not on Java 8?

If you're not on Java 8, you can't use LocalDate either.

Replacing the containsKey() with a get() just made things worse, because you're still performing the lookup a second time with the second call to get(), except now you've lost expressiveness. You should just call get() once:

Ioanna Katsanou
Ranch Hand
Posts: 182
1
• Number of slices to send:
Optional 'thank-you' note:
oh Stephan thanks !!
I am not in Java se8, because the company I work for uses se7!
The truth is I did not get the time to actually test the code after the last changes , and only wrote them on the post, therefore did not notice the thing about the LocalDate !!
Ok I am going to implement now everything properly !!

Thanks again ! You saved my day

 Did you see how Paul cut 87% off of his electric heat bill with 82 watts of micro heaters?