Sorting by property in Java 8 stream

JavaSortingLambdaJava 8Java Stream

Java Problem Overview


Oh, those tricky Java 8 streams with lambdas. They are very powerful, yet the intricacies take a bit to wrap one's header around it all.

Let's say I have a User type with a property User.getName(). Let's say I have a map of those users Map<String, User> associated with names (login usernames, for example). Let's further say I have an instance of a comparator UserNameComparator.INSTANCE to sort usernames (perhaps with fancy collators and such).

So how do I get a list of the users in the map, sorted by username? I can ignore the map keys and do this:

return userMap.values()
    .stream()
    .sorted((u1, u2) -> {
      return UserNameComparator.INSTANCE.compare(u1.getName(), u2.getName());
    })
    .collect(Collectors.toList());

But that line where I have to extract the name to use the UserNameComparator.INSTANCE seems like too much manual work. Is there any way I can simply supply User::getName as some mapping function, just for the sorting, and still get the User instances back in the collected list?

Bonus: What if the thing I wanted to sort on were two levels deep, such as User.getProfile().getUsername()?

Java Solutions


Solution 1 - Java

What you want is Comparator#comparing:

userMap.values().stream()
    .sorted(Comparator.comparing(User::getName, UserNameComparator.INSTANCE))
    .collect(Collectors.toList());

For the second part of your question, you would just use

Comparator.comparing(
    u->u.getProfile().getUsername(), 
    UserNameComparator.INSTANCE
)

Solution 2 - Java

for comparing in the level two, you can proceed like that : for the object

public class ArticleChannel {

    private Long id;
    private String label;
    private ArticleBusiness business;
}

public class ArticleBusiness {
    private Long id;
    private String name;
}

articleChannelList.sort(Comparator.comparing((ArticleChannel articleChannel) -> **articleChannel.getBusiness().getName()**).thenComparing(ArticleChannel::getLabel));

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGarret WilsonView Question on Stackoverflow
Solution 1 - JavaMishaView Answer on Stackoverflow
Solution 2 - JavaMirloView Answer on Stackoverflow