views:

155

answers:

5
HashMap selections = new HashMap<Integer, Float>();

How can i get the Integer key of the 3rd smaller value of Float in all HashMap?

Edit im using the HashMap for this

for (InflatedRunner runner : prices.getRunners()) {
       for (InflatedMarketPrices.InflatedPrice price : runner.getLayPrices()) {
           if (price.getDepth() == 1) {
             selections.put(new Integer(runner.getSelectionId()), new Float(price.getPrice()));
           }
         }                    

}

i need the runner of the 3rd smaller price with depth 1

maybe i should implement this in another way?

+1  A: 

You have to do it in steps:

  1. Get the Collection<V> of values from the Map
  2. Sort the values
  3. Choose the index of the nth smallest

Think about how you want to handle ties.

duffymo
If you're sorting `Collection<Float>`, how are you going to "unmap" the `Float` back to the `Integer` in the map?
polygenelubricants
+2  A: 

Are you sure you're using hashmaps right? They're used to quickly lookup a value given a key; it's highly unusual to sort the values and then try to find a corresponding key. If anything, you should be mapping the float to the int, so you could at least sort the float keys and get the integer value of the third smallest that way

Michael Mrozek
+3  A: 

Michael Mrozek nails it with his question if you're using HashMap right: this is highly atypical scenario for HashMap. That said, you can do something like this:

  • get the Set<Map.Entry<K,V>> from the HashMap<K,V>.entrySet().
  • addAll to List<Map.Entry<K,V>>
  • Collections.sort the list with a custom Comparator<Map.Entry<K,V>> that sorts based on V.

//after edit

It looks like selection should really be a SortedMap<Float, InflatedRunner>. You should look at java.util.TreeMap.

Here's an example of how TreeMap can be used to get the 3rd lowest key:

TreeMap<Integer,String> map = new TreeMap<Integer,String>();
map.put(33, "Three");
map.put(44, "Four");
map.put(11, "One");
map.put(22, "Two");

int thirdKey = map.higherKey(map.higherKey(map.firstKey()));
System.out.println(thirdKey); // prints "33"

Also note how I take advantage of Java's auto-boxing/unboxing feature between int and Integer. I noticed that you used new Integer and new Float in your original code; this is unnecessary.


//another edit

It should be noted that if you have multiple InflatedRunner with the same price, only one will be kept. If this is a problem, and you want to keep all runners, then you can do one of a few things:

  • If you really need a multi-map (one key can map to multiple values), then you can:
  • If you don't need the map functionality, then just have a List<RunnerPricePair> (sorry, I'm not familiar with the domain to name it appropriately), where RunnerPricePair implements Comparable<RunnerPricePair> that compares on prices. You can just add all the pairs to the list, then either:
    • Collections.sort the list and get the 3rd pair
    • Use O(N) selection algorithm
polygenelubricants
im gonna try this :D
Daniel
then i use firstKey 3 times right and get the 3rd right?
Daniel
@Daniel: I added example using `firstKey` and `higherKey`.
polygenelubricants
this works, but there is a problem.. when two equal floats are found.. and used as keys..
Daniel
@Daniel: Yes, in that case only one of them will be kept. I assumed that you have some sort of bidding scheme or something, and you just need one rep for each price, and you want the 3rd lowest price, etc. I've added some more suggestions, hope it helps.
polygenelubricants
A: 

If you regularly need to get the key of the nth item, consider:

  • using a TreeMap, which efficiently keeps keys in sorted order
  • then using a double map (i.e. one TreeMap mapping integer > float, the other mapping float > integer)

You have to weigh up the inelegance and potential risk of bugs from needing to maintain two maps with the scalability benefit of having a structure that efficiently keeps the keys in order.

You may need to think about two keys mapping to the same float...

P.S. Forgot to mention: if this is an occasional function, and you just need to find the nth largest item of a large number of items, you could consider implementing a selection algorithm (effectively, you do a sort, but don't actually bother sorting subparts of the list that you realise you don't need to sort because their order makes no difference to the position of the item you're looking for).

Neil Coffey
A: 

You could do it with the google collections BiMap, assuming that the Floats are unique.

TofuBeer