Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I sort a list of maps by value of some specific key using Java 8?

How can I sort a List of Map<String, String> using Java 8? The map contains a key called last_name, and the value associated with it may be null. I'm not sure how to do it because the following results in a compiler error:

List<Map<String, String>> peopleList = ...

peopleList.sort(Comparator.comparing(Map::get, Comparator.nullsLast(Comparator.naturalOrder())));

Is using an anonymous class the only way to do it?

Note that I am not trying to sort each map in the list. I want to sort the list itself based on a key in each map.

like image 649
BJ Dela Cruz Avatar asked Jun 13 '17 19:06

BJ Dela Cruz


3 Answers

It looks like you can rewrite your code like

peopleList.sort(Comparator.comparing(
                    m -> m.get("yourKey"), 
                    Comparator.nullsLast(Comparator.naturalOrder()))
               )
like image 57
Pshemo Avatar answered Sep 19 '22 04:09

Pshemo


Since your peopleList might contain a null and the Map::key might have a null value, you probably need to nullsLast twice:

peopleList.sort(Comparator.nullsLast(Comparator.comparing(m -> m.get("last_name"),
                            Comparator.nullsLast(Comparator.naturalOrder()))));
like image 31
Eugene Avatar answered Sep 17 '22 04:09

Eugene


This should fit your requirement.

peopleList.sort((o1, o2) -> o1.get("last_name").compareTo(o2.get("last_name")));

In case you want handle the null pointer try this "old fashion" solution:

peopleList.sort((o1, o2) ->
{
  String v1 = o1.get("last_name");
  String v2 = o2.get("last_name");
  return (v1 == v2) ? 0 : (v1 == null ? 1 : (v2 == null ? -1 : v1.compareTo(v2))) ;
});

Switch 1 and -1 if you want the null values first or last.

For thoroughness' sake I've added the generator of useful test cases:

Random random = new Random();

random.setSeed(System.currentTimeMillis());

IntStream.range(0, random.nextInt(20)).forEach(i -> {
  Map<String, String> map1 = new HashMap<String, String>();
  String name = new BigInteger(130, new SecureRandom()).toString(6);
  if (random.nextBoolean())
    name = null;
  map1.put("last_name", name);
  peopleList.add(map1);
});
like image 29
freedev Avatar answered Sep 18 '22 04:09

freedev