Home  >  Article  >  Java  >  A brief discussion of Java's Map sort by value (Map sort by value)

A brief discussion of Java's Map sort by value (Map sort by value)

高洛峰
高洛峰Original
2017-01-19 10:54:331648browse

Map is a collection of key-value pairs, also called a dictionary or associative array, etc. It is one of the most common data structures. How to sort a map by value in java? It seems simple, but it is not easy!

For example, the key in the Map is of type String, which represents a word, and the value is of type int, which represents the number of times the word appears. Now we want to sort by the number of times the word appears:

Map map = new TreeMap();
map.put("me", 1000);
map.put("and", 4000);
map.put("you", 3000);
map.put("food", 10000);
map.put("hungry", 5000);
map.put("later", 6000);

The result of sorting by value should be:

key value
me 1000
you 3000
and 4000
hungry 5000
later 6000
food 10000

First of all, the SortedMap structure cannot be used, because SortedMap is a Map sorted by key, not a Map sorted by value , what we want is a Map sorted by value.

Couldn't you do this with a SortedMap?
No, because the map are being sorted by its keys.

Method 1:

The following Java code:

import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
 
public class Main {
  public static void main(String[] args) {
 
    Set set = new TreeSet();
    set.add(new Pair("me", "1000"));
 
    set.add(new Pair("and", "4000"));
    set.add(new Pair("you", "3000"));
 
    set.add(new Pair("food", "10000"));
    set.add(new Pair("hungry", "5000"));
 
    set.add(new Pair("later", "6000"));
    set.add(new Pair("myself", "1000"));
 
    for (Iterator i = set.iterator(); i.hasNext();)
 
      System.out.println(i.next());
  }
}
 
class Pair implements Comparable {
  private final String name;
  private final int number;
 
  public Pair(String name, int number) {
    this.name = name;
    this.number = number;
  }
 
  public Pair(String name, String number) throws NumberFormatException {
    this.name = name;
    this.number = Integer.parseInt(number);
 
  }
 
  public int compareTo(Object o) {
    if (o instanceof Pair) {
      int cmp = Double.compare(number, ((Pair) o).number);
      if (cmp != 0) {
        return cmp;
      }
      return name.compareTo(((Pair) o).name);
    }
 
    throw new ClassCastException("Cannot compare Pair with "
        + o.getClass().getName());
 
  }
 
  public String toString() {
    return name + ' ' + number;
  }
}

Similar C++ code:

typedef pair<string, int> PAIR;
 
int cmp(const PAIR& x, const PAIR& y)
{
  return x.second > y.second;
}
 
map<string,int> m;
vector<PAIR> vec;
for (map<wstring,int>::iterator curr = m.begin(); curr != m.end(); ++curr)
{
  vec.push_back(make_pair(curr->first, curr->second));
}
sort(vec.begin(), vec.end(), cmp);

Above The essential meaning of the method is: encapsulate the key-value pairs (Map.Entry) in the Map structure into a custom class (structure), or use the Map.Entry class directly. The custom class knows how it should be sorted, that is, sorted by value. Specifically, it implements the Comparable interface or constructs a Comparator object for itself, and then uses an ordered set (SortedSet, TreeSet is an implementation of SortedSet) instead of a Map structure, so that The purpose of sort by value in Map is achieved. That is to say, instead of using Map, treat Map.Entry as an object, so the problem becomes to implement an ordered collection of the object or to sort the collection of the object. You can either use a SortedSet, so that it will be naturally ordered after the insertion is completed, or you can use a List or array and then sort it (Collections.sort() or Arrays.sort()).

Encapsulate the information in its own class. Either implement
Comparable and write rules for the natural ordering or write a
Comparator based on your criteria. Store the information in a sorted
collection, or use the Collections.sort() method.

Method 2:

You can also use the following code to sort by value:

public static Map sortByValue(Map map) {
    List list = new LinkedList(map.entrySet());
    Collections.sort(list, new Comparator() {
 
      public int compare(Object o1, Object o2) {
        return ((Comparable) ((Map.Entry) (o1)).getValue())
            .compareTo(((Map.Entry) (o2)).getValue());
 
      }
    });
    Map result = new LinkedHashMap();
 
    for (Iterator it = list.iterator(); it.hasNext();) {
      Map.Entry entry = (Map.Entry) it.next();
      result.put(entry.getKey(), entry.getValue());
    }
    return result;
  }
 
  public static Map sortByValue(Map map, final boolean reverse) {
    List list = new LinkedList(map.entrySet());
    Collections.sort(list, new Comparator() {
 
      public int compare(Object o1, Object o2) {
        if (reverse) {
          return -((Comparable) ((Map.Entry) (o1)).getValue())
              .compareTo(((Map.Entry) (o2)).getValue());
        }
        return ((Comparable) ((Map.Entry) (o1)).getValue())
            .compareTo(((Map.Entry) (o2)).getValue());
      }
    });
 
    Map result = new LinkedHashMap();
    for (Iterator it = list.iterator(); it.hasNext();) {
      Map.Entry entry = (Map.Entry) it.next();
      result.put(entry.getKey(), entry.getValue());
    }
    return result;
  }
 
 
 
 
        Map map = new HashMap();
    map.put("a", 4);
    map.put("b", 1);
    map.put("c", 3);
    map.put("d", 2);
    Map sorted = sortByValue(map);
    System.out.println(sorted);
// output : {b=1, d=2, c=3, a=4}
 
或者还可以这样:
Map map = new HashMap();
    map.put("a", 4);
    map.put("b", 1);
    map.put("c", 3);
    map.put("d", 2);
 
    Set<Map.Entry<String, Integer>> treeSet = new TreeSet<Map.Entry<String, Integer>>(
        new Comparator<Map.Entry<String, Integer>>() {
          public int compare(Map.Entry<String, Integer> o1,
              Map.Entry<String, Integer> o2) {
            Integer d1 = o1.getValue();
            Integer d2 = o2.getValue();
            int r = d2.compareTo(d1);
 
            if (r != 0)
              return r;
            else
              return o2.getKey().compareTo(o1.getKey());
          }
 
        });
    treeSet.addAll(map.entrySet());
    System.out.println(treeSet);
    // output : [a=4, c=3, d=2, b=1]

In addition, sort map by value is implemented in Groovy. Of course, the essence is the same, but it is very simple:

Use the sort method of map in groovy (requires groovy 1.6),

def result = map.sort(){ a, b ->
      b.value.compareTo(a.value)
    }

For example:

["a":3,"b":1,"c":4,"d":2].sort{ a,b -> a.value - b.value }

The result is: [b:1, d:2, a:3, c:4]

It’s similar in Python:

h = {"a":2,"b":1,"c":3}
i = h.items() // i = [(&#39;a&#39;, 2), (&#39;c&#39;, 3), (&#39;b&#39;, 1)]
i.sort(lambda (k1,v1),(k2,v2): cmp(v2,v1) ) // i = [(&#39;c&#39;, 3), (&#39;a&#39;, 2), (&#39;b&#39;, 1)]

The above article briefly talks about Map sorting by value in Java (Map sort by value) is all the content shared by the editor. I hope it can To give you a reference, I also hope that everyone will support the PHP Chinese website.

For more articles related to Java’s Map sorting by value (Map sort by value), please pay attention to the PHP Chinese website!


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn