简体   繁体   中英

How to sort a Map by Value (ArrayList) size in Java?

I have the following Map:

    Map<String, List<String>> map = new HashMap<String, List<String>>();

which is filled with pairs of keys and values.
For example: key = student name and value = family members names.
I want to sort the map by the size of the list of strings. I have tried implementing Comparator with a TreeMap but I got an error so I switched back to HashMap. Any ideas?

You should use the HashMap unordered, and then each time you want to order, put all the values of the HashMap into a TreeMap, using a Comparator that has the HashMap as a variable.

Then, for each key you compare, you get the value of the HashMap (the list) and check the list size. So you compare by the list sizes, returning -1, 0 or 1 depending on the case.

Once you finish what you need, you discard that TreeMap.

If you try to use only a TreeMap, then you'll see that you are ordering the keys according to a value that is not a property of such key. In this case, the length of the value (a list). So, there may exist a function that increases the length of the list, and the TreeMap won't even notice.

Some code:

public class ListSizeComparator implements Comparator<String> {

private final Map<String, List<String>> map;

public ListSizeComparator(final Map<String, List<String>> map) {
    this.map = map;
}

@Override
public int compare(String s1, String s2) {
    //Here I assume both keys exist in the map.
    List<String> list1 = this.map.get(s1);
    List<String> list2 = this.map.get(s2);
    Integer length1 = list1.size();
    Integer length2 = list2.size();
    return length1.compareTo(length2);
}

}

The solution is more or less identical to https://stackoverflow.com/a/8897384/869736 , but all you need to do is write a Comparator that compares lists by their length.

Comparator<List<String>> lengthComparator = new Comparator<List<String>>() {
  public int compare(List<String> a, List<String> b) {
    return a.size() - b.size(); 
    // size() is always nonnegative, so this won't have crazy overflow bugs
  }
};

and then just use the solution outlined there.

I see three choices here:

  1. Sort the map contents every time you need - if it's not too often that it's OK.
  2. In addition to the map store other auxiliary structure with desired order, for example TreeMap<Integer, List<String>> (key - number of family members, value - list of students).
  3. May be you don't need at all your map as you described it and following map will be sufficient: TreeMap<Integer, Map<String, List<String>>> (key - number of family members, value - part of your original map containing students with number of family members equal $key).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM