Win a 3 month subscription to Marco Behler Videos this week in the Spring forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Compare values in HashMap - Efficient Problem Sovling  RSS feed

 
Ioanna Katsanou
Ranch Hand
Posts: 111
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
 
Stephan van Hulst
Saloon Keeper
Posts: 7507
135
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 111
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey Stephan,

thank you so much for your answer !!

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

  
 
Ioanna Katsanou
Ranch Hand
Posts: 111
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 7507
135
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 7507
135
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 111
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 7507
135
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 111
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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     
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!