Reputation: 21356
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()
?
Upvotes: 67
Views: 66355
Reputation: 674
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));
Upvotes: 1
Reputation: 28133
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
)
Upvotes: 100