73

I have map Map<Type, Long> countByType and I want to have a list which has sorted (min to max) keys by their corresponding values. My try is:

countByType.entrySet().stream().sorted().collect(Collectors.toList());

however this just gives me a list of entries, how can I get a list of types, without losing the order?

Alexis C.
  • 91,686
  • 21
  • 171
  • 177
adaPlease
  • 835
  • 1
  • 6
  • 8

6 Answers6

141

You say you want to sort by value, but you don't have that in your code. Pass a lambda (or method reference) to sorted to tell it how you want to sort.

And you want to get the keys; use map to transform entries to keys.

List<Type> types = countByType.entrySet().stream()
        .sorted(Comparator.comparing(Map.Entry::getValue))
        .map(Map.Entry::getKey)
        .collect(Collectors.toList());
Jesper
  • 202,709
  • 46
  • 318
  • 350
  • 45
    ... or `.sorted(Map.Entry.comparingByValue())` – Alexis C. May 24 '15 at 17:21
  • After chaining `sorted` how can I get the stream back to a map? Well technically I know I couldn't revert it to a map because its sets are not ordered. But I would want to print the map like this `.forEach((k,v) -> System.out.println(k + ": " + v)`. How can I achieve this using that stream? – dabadaba May 10 '16 at 11:35
  • @dabadaba after the `.sorted(...)` you have a stream of entries, so you could append `.forEach(e -> System.out.println(e.getKey() + ": " + e.getValue()));` – Jesper May 10 '16 at 11:39
  • @Jesper got it, thanks! And last but not least, how can I get the reversed order? I am using `.sorted(Map.Entry.comparingByValue())` – dabadaba May 10 '16 at 11:42
  • 1
    @dabadaba you can use `.reversed()` but because of limitations in type inference you need to specify type arguments: `.sorted(Map.Entry.comparingByValue().reversed())` – Jesper May 10 '16 at 11:54
  • 1
    @Jesper I actually figured out doing it this way: `.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))` – dabadaba May 10 '16 at 12:01
12

You have to sort with a custom comparator based on the value of the entry. Then select all the keys before collecting

countByType.entrySet()
           .stream()
           .sorted((e1, e2) -> e1.getValue().compareTo(e2.getValue())) // custom Comparator
           .map(e -> e.getKey())
           .collect(Collectors.toList());
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
3

You can sort a map by value as below, more example here

//Sort a Map by their Value.
Map<Integer, String> random = new HashMap<Integer, String>();

random.put(1,"z");
random.put(6,"k");
random.put(5,"a");
random.put(3,"f");
random.put(9,"c");

Map<Integer, String> sortedMap =
        random.entrySet().stream()
                .sorted(Map.Entry.comparingByValue())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (e1, e2) -> e2, LinkedHashMap::new));
System.out.println("Sorted Map: " + Arrays.toString(sortedMap.entrySet().toArray()));
Tunaki
  • 132,869
  • 46
  • 340
  • 423
Ajay Kumar
  • 4,864
  • 1
  • 41
  • 44
3
Map<Integer, String> map = new HashMap<>();
map.put(1, "B");
map.put(2, "C");
map.put(3, "D");
map.put(4, "A");

List<String> list = map.values()
                       .stream()
                       .sorted()
                       .collect(Collectors.toList());

Output: [A, B, C, D]

RubioRic
  • 2,442
  • 4
  • 28
  • 35
Kannan Msk
  • 157
  • 1
  • 6
3

You can use this as an example of your problem

    Map<Integer, String> map = new HashMap<>();
    map.put(10, "apple");
    map.put(20, "orange");
    map.put(30, "banana");
    map.put(40, "watermelon");
    map.put(50, "dragonfruit");

    // split a map into 2 List
    List<Integer> resultSortedKey = new ArrayList<>();
    List<String> resultValues = map.entrySet().stream()
            //sort a Map by key and stored in resultSortedKey
            .sorted(Map.Entry.<Integer, String>comparingByKey().reversed())
            .peek(e -> resultSortedKey.add(e.getKey()))
            .map(x -> x.getValue())
            // filter banana and return it to resultValues
            .filter(x -> !"banana".equalsIgnoreCase(x))
            .collect(Collectors.toList());

    resultSortedKey.forEach(System.out::println);
    resultValues.forEach(System.out::println);
MADHUR GUPTA
  • 1,014
  • 10
  • 14
2

Here is the simple solution with StreamEx

EntryStream.of(countByType).sortedBy(e -> e.getValue()).keys().toList();
user_3380739
  • 1
  • 14
  • 14