简体   繁体   中英

Sort HashMap of ArrayList Based on ArrayList5 Size

I realize there are questions similar to this, but they do not answer my question.

I need to return the keys of my HashMap, based on the size of the corresponding value's ArrayList. For example, if I have:

HashMap<String,ArrayList<Integer>> unsortedMap = new HashMap<String,ArrayList<Integer>>();
unsortedMap.put("A",new ArrayList<Integer>(Arrays.asList(1,2,3)));
unsortedMap.put("B",new ArrayList<Integer>(Arrays.asList(4)));
unsortedMap.put("C",new ArrayList<Integer>(Arrays.asList(2,3,1,4)));

I'd like it to return "C" "A" "B"

For Java 7, you can call entrySet() to get a Set<Map.Entry<String,ArrayList<Integer>>> - which you can then use to populate something like an ArrayList<Map.Entry<String,ArrayList<Integer>>> which you can sort with a custom comparator.

import java.util.*;

public class Test {
  public static void main(String[] args) {
    Map<String, ArrayList<Integer>> unsortedMap = new HashMap<>();
    unsortedMap.put("A", new ArrayList<Integer>(Arrays.asList(1, 2, 3)));
    unsortedMap.put("B", new ArrayList<Integer>(Arrays.asList(4)));
    unsortedMap.put("C", new ArrayList<Integer>(Arrays.asList(2, 3, 1, 4)));

    List<Map.Entry<String, ArrayList<Integer>>> list = 
        new ArrayList<>(unsortedMap.entrySet());
    Collections.sort(list, new EntryComparator());

    for (Map.Entry<String, ArrayList<Integer>> entry : list) {
      System.out.println(entry.getKey());
    }
  }

  private static class EntryComparator
      implements Comparator<Map.Entry<String, ArrayList<Integer>>>
  {
    public int compare(Map.Entry<String, ArrayList<Integer>> left,
        Map.Entry<String, ArrayList<Integer>> right) {     
      // Right then left to get a descending order
      return Integer.compare(right.getValue().size(), left.getValue().size());
    }
  }
}

In Java 8 you can use the streams API to make it slightly more fluent - while taking basically the same steps.

import java.util.*;
import java.util.stream.*;

public class Test {
  public static void main(String[] args) {
    Map<String, ArrayList<Integer>> unsortedMap = new HashMap<>();
    unsortedMap.put("A", new ArrayList<Integer>(Arrays.asList(1, 2, 3)));
    unsortedMap.put("B", new ArrayList<Integer>(Arrays.asList(4)));
    unsortedMap.put("C", new ArrayList<Integer>(Arrays.asList(2, 3, 1, 4)));

    List<String> keys = unsortedMap
          .entrySet()
          .stream()
          .sorted((left, right) ->
              Integer.compare(right.getValue().size(), left.getValue().size()))
          .map(entry -> entry.getKey())
          .collect(Collectors.toList());

    for (String key : keys) {
      System.out.println(key);
    }
  }
}

If you are using , here's also a way to do this:

List<String> keys = unsortedMap.entrySet()
                   .stream()
                   .sorted((e1, e2) -> Integer.compare(e2.getValue().size(), e1.getValue().size()))
                   .map(Map.Entry::getKey)
                   .collect(Collectors.toList());
System.out.println(keys); //[C, A, B]

What it does is:

  • get a Stream of the entries of your map
  • sort the entries by the the size of each arraylist
  • map each entry to its corresponding key
  • collect the result in a List

If you want you could also write the sorted line as :

.sorted(Comparator.comparing(e -> e.getValue().size(), Comparator.reverseOrder()))

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