0

how to get 2 biggest value in hashmap? eg. i have collection{ dare = 10, to =20, be =15, different = 10}, if we count manually the first biggest value is 20 that the key is to, and the second biggest value is 15 the key is be, According to Finding Key associated with max Value in a Java Map i use:

 Map.Entry<String, Float> max1 = null;
 Map.Entry<String, Float> max2 = null;

      //searching the first biggest value
      for(Map.Entry<String, Float> en : TFIDF.entrySet()){
          if (max1 == null || en.getValue().compareTo(max1.getValue()) > 0){
              max1 = en;
              }                   
      }
      //searching the second biggest value
      for(Map.Entry<String, Float> en : TFIDF.entrySet()){
          if (max2 == null || en.getValue().compareTo(max2.getValue()) <= max1.getValue()){
              max2 = en;
              }                   
      }

but after i compare with the max1 the value return the min value.

Community
  • 1
  • 1
zeptyan
  • 35
  • 1
  • 2
  • 6
  • And what if two values compare to the same? – fge Feb 26 '14 at 08:14
  • The core of your problem is that compareTo(max2.getValue()) <= max1.getValue() is not a valid check (one is a value, the other is just greater-than, equal-to or less-than zero. Anyway it's simpler to just do the same thing you did on the first loop, but ignore the iteration that has the first result in it. – Ted Bigham Feb 26 '14 at 08:54
  • yups, thanks for the help Ted Bigham – zeptyan Feb 26 '14 at 09:06

3 Answers3

1

First, you have to initialize max1 and max2 because the null-check skips it every time and then in the second loop you compare the result of compareTo with the actual value, but compareTo returns -1, 0 or 1 and is therefore most likely smaller every time.

EDIT To increase readability of your code, I would suggest something like sorting the entry set descending by a Comparator working on the value part of the entries and then fetching the first and second entry.

Smutje
  • 17,733
  • 4
  • 24
  • 41
1

as this code

 en.getValue().compareTo(max2.getValue()) <= max1.getValue())

will always be true when max2 is less than max1's value

I think what you want is

if (max2 == null || en.getValue().compareTo(max2.getValue()) > 0 
              && en.getValue().compareTo(max1.getValue() < 0)) {
         max2 = en;
}  

The above will return the second highest values.

Scary Wombat
  • 44,617
  • 6
  • 35
  • 64
  • I think restricting by value for max2 could be problematic if there are two entries with the same max value. Although the order will be undefined, it should probably at least return the two max entries. – Ted Bigham Feb 26 '14 at 08:24
  • @TedBigham Updated with code that handles your scenario, although max2 will always have a value. – Scary Wombat Feb 26 '14 at 08:30
  • I believe your update would cause the same entry to be returned for both max1 and max2, wouldn't it? You're testing for less than or equal to max1, which is true for all numbers in the set. – Ted Bigham Feb 26 '14 at 08:35
  • @TedBigham `gt max2 && lte max1` - yes if two mapEntries have the same max values, then in the second code the same value will be returned. – Scary Wombat Feb 26 '14 at 08:41
  • Even if there's only one max, it looks like it will always just return the max value for both max1 and max2. [lte max1] does not filter out max1 like your first one does with [lt max1] – Ted Bigham Feb 26 '14 at 08:48
  • (full disclosure) that's why i prefer my answer. It specifically filters out the first answer (max1), instead of using it's value. – Ted Bigham Feb 26 '14 at 08:51
  • yeah this code return the same value as max1, i just tried – zeptyan Feb 26 '14 at 08:51
  • zeptyan I think the first version should work as you require. – Scary Wombat Feb 26 '14 at 08:53
  • @TedBigham Yes, but because on the first iteration `max2` is null, it will shortcut the if statement and will be set. I was feeling that in your version, if all values were the same then max2 would never be set. – Scary Wombat Feb 26 '14 at 08:54
  • deleted second version. – Scary Wombat Feb 26 '14 at 08:56
  • I see what you mean, but notice i'm using the reference compare != instead of equals(). The only way max2 would not be set in my version, is if there was only one entry in the map. Which also *seems* like the right result. – Ted Bigham Feb 26 '14 at 08:56
0

This check...

if (max2 == null || en.getValue().compareTo(max2.getValue()) <= max1.getValue()){

should probably be something more like...

if (en != max1 && (max2 == null || (en.getValue().compareTo(max2.getValue()) >0)) {
Ted Bigham
  • 4,237
  • 1
  • 26
  • 31