Search for the highest n values โ€‹โ€‹on the map

I have a large String-> Integer map, and I want to find the top 5 values โ€‹โ€‹on the map. My current approach involves translating a map into a list of an array of a pair's object (key, value), and then sorting using Collections.sort () before accepting the first 5. It is possible that the key updated its value during the operation.

I think this approach is acceptable single-threaded, but if I had multiple threads, they all started transposing and sorting often, it doesn't seem very efficient. An alternative, apparently, is to save a separate list of 5 items and update it when performing the corresponding operations on the map.

Can I offer several options / alternatives to optimize this? I am happy to consider various data structures, if any.

Thanks!

+7
java optimization algorithm data-structures
source share
7 answers

I think this approach is acceptable single-threaded, but if I had multiple threads, they all started transposing and sorting often, it doesn't seem very efficient. An alternative, apparently, is to save a separate list of 5 items and update it when performing the corresponding operations on the map.

There is an intermediate approach that you can take as well. When the stream requests a "sorted view" on the map, create a copy of the map and then process its sorting.

public List<Integer> getMaxFive() { Map<String, Integer> copy = null; synchronized(lockObject) { copy = new HashMap<String, Integer>(originalMap); } //sort the copy as usual return list; } 

Ideally, if you have a certain state (for example, this card) that is accessed by several threads, you encapsulate the state after another class so that each thread does not update the map directly.

+2
source share

Well, to find the top 5 values โ€‹โ€‹on a map, you can do it at O(n) time, when a sort will be slower than that.

The easiest way is to simply execute the for loop through the Map recordset.

 for (Entry<String, Integer> entry: map.entrySet()) { if (entry.getValue() > smallestMaxSoFar) updateListOfMaximums(); } 
+5
source share

You can use two Maps:

 // Map name to value Map<String, Integer> byName // Maps value to names NavigableMap<Integer, Collection<String>> byValue 

and always keep them in sync (maybe wrap both in a different class that is responsible for put, get, etc.). For highest values, use byValue.navigableKeySet().descendingIterator() .

+3
source share

I would create a method like:

 private static int[] getMaxFromMap(Map<String, Integer> map, int qty) { int[] max = new int[qty]; for (int a=0; a<qty; a++) { max[a] = Collections.max(map.values()); map.values().removeAll(Collections.singleton(max[a])); if (map.size() == 0) break; } return max; } 

Using Collections.max() and Collections.singleton()

+1
source share

There are two ways to make this easy:

  • Place the map in the heap structure and extract the elements n that you want from it.
  • Scroll the map and update the list of n highest values โ€‹โ€‹using each entry.

If you want to get an unknown or a large number of highest values, the first method is the method. If you have a fixed small number of values โ€‹โ€‹to extract, the second may be easier to understand for some programmers. Personally, I prefer the first method.

+1
source share

Try using a different data structure. Suppose there is a class called MyClass, which is its attribute (String) and value (int). MyClass, of course, should implement the Comparable interface. Another approach is to create a class called MyClassComparator that extends Comparator.

The compareTo method (no matter where it is) should be defined as follows: CompareTo (parameters) {return value2 - value1; // downstream}

The rest is easy. Using List and calling the Collections.sort (parameters) method will do the sorting.

I don't know which sorting algorithm uses Collections.sort (parameters). But if you feel that some data may come with time, you will need to sort the insert. Since it is good for data that is almost sorted and online .

0
source share

If the changes are rare, I would do some SortedByValHashMap<K,V> extends HashMap <K,V> , similar to LinkedHashMap ) that keep records sorted by value.

0
source share

All Articles