Sort map by value

This example will demonstrate how to sort a map based on values. In the set up, we will create a map of candy bars keyed by calories and value of the name of the candy bar. Then each snippet will show how to order the hashmap by value. In a comparable example we demonstrate how to sort a dictionary or hashmap by value in groovy.

Setup

Map<Integer, String> CANDY_BARS;

@Before
public void setUp () {

    CANDY_BARS = new HashMap<Integer, String>();
    CANDY_BARS.put(233, "REESE'S P-BUTTER CUPS");
    CANDY_BARS.put(222, "REESE'S P-BUTTER CUPS");
    CANDY_BARS.put(284, "TWIX, CARAMEL");
    CANDY_BARS.put(232, "ALMOND JOY");
    CANDY_BARS.put(149, "YORK PEPPERMINT PATTIE");
}

Straight up Java

First creating a java Comparator, this snippet will sort map values in ascending order by passing the comparator to Collections.sort.

@Test
public void sort_map_by_values_java () {

    Comparator<Map.Entry<Integer, String>> byMapValues = new Comparator<Map.Entry<Integer, String>>() {
        @Override
        public int compare(Map.Entry<Integer, String> left, Map.Entry<Integer, String> right) {
            return left.getValue().compareTo(right.getValue());
        }
    };

    // create a list of map entries
    List<Map.Entry<Integer, String>> candyBars = new ArrayList<Map.Entry<Integer, String>>();

    // add all candy bars
    candyBars.addAll(CANDY_BARS.entrySet());

    // sort the collection
    Collections.sort(candyBars, byMapValues);

    logger.info(candyBars);

    assertEquals("ALMOND JOY", candyBars.get(0).getValue());
}

Output

[
    232=ALMOND JOY,
    222=REESE'S P-BUTTER CUPS,
    233=REESE'S P-BUTTER CUPS,
    284=TWIX, CARAMEL,
    149=YORK PEPPERMINT PATTIE
]

Java 8

This snippet will sort hashmap by value in descending order using java 8. Using a lambda expression we will create a comparator that will compare each entry value. Next calling calling the Stream.sort we will pass the comparator then calling Comparator.reverse.

@Test
public void sort_map_by_values_java8() {

    Comparator<Entry<Integer, String>> byValue = (entry1, entry2) -> entry1.getValue().compareTo(
            entry2.getValue());

    Optional<Entry<Integer, String>> val = CANDY_BARS
            .entrySet()
            .stream()
            .sorted(byValue.reversed())
            .findFirst();

    logger.info(val);

    assertEquals("YORK PEPPERMINT PATTIE", val.get().getValue());
}

Google Guava

First lets define comparator using guava's fluent Ordering utility that will be used in the snippets below.

Ordering<Map.Entry<Integer, String>> byMapValues = new Ordering<Map.Entry<Integer, String>>() {
   @Override
   public int compare(Map.Entry<Integer, String> left, Map.Entry<Integer, String> right) {
        return left.getValue().compareTo(right.getValue());
   }
};

Natural order

This snippet will show how to sort a hashmap based on values using guava ordering comparator class.


@Test
public void sort_map_by_values_guava () {

    // create a list of map entries
    List<Map.Entry<Integer, String>> candyBars = Lists.newArrayList(CANDY_BARS.entrySet());

    Collections.sort(candyBars, byMapValues);

    logger.info(candyBars);

    assertEquals("ALMOND JOY", candyBars.get(0).getValue());
}

Output

[
    232=ALMOND JOY,
    222=REESE'S P-BUTTER CUPS,
    233=REESE'S P-BUTTER CUPS,
    284=TWIX, CARAMEL,
    149=YORK PEPPERMINT PATTIE
]

Reverse order

Using the Ordering object created above, we will call the Ordering.reverse which will sort the map in descending order.


@Test
public void sort_map_by_values_guava_reverse () {

    // create a list of map entries
    List<Map.Entry<Integer, String>> candyBars = Lists.newArrayList(CANDY_BARS.entrySet());

    Collections.sort(candyBars, byMapValues.reverse());

    logger.info(candyBars);

    assertEquals("YORK PEPPERMINT PATTIE", candyBars.get(0).getValue());
}

Output

[
    149=YORK PEPPERMINT PATTIE,
    284=TWIX, CARAMEL,
    222=REESE'S P-BUTTER CUPS,
    233=REESE'S P-BUTTER CUPS,
    232=ALMOND JOY
]