简体   繁体   English

在 Java 8 流中按属性排序

[英]Sorting by property in Java 8 stream

Oh, those tricky Java 8 streams with lambdas.哦,那些带有 lambda 表达式的棘手 Java 8 流。 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() .假设我有一个带有属性User.getName()User类型。 Let's say I have a map of those users Map<String, User> associated with names (login usernames, for example).假设我有这些用户的Map<String, User>与名称(例如,登录用户名)相关联。 Let's further say I have an instance of a comparator UserNameComparator.INSTANCE to sort usernames (perhaps with fancy collators and such).让我们进一步说,我有一个比较器UserNameComparator.INSTANCE的实例来对用户UserNameComparator.INSTANCE进行排序(也许有花哨的校对器等)。

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.但是我必须提取名称以使用UserNameComparator.INSTANCE那一行似乎手动工作太多。 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?有什么方法可以简单地提供User::getName作为某种映射函数,仅用于排序,并且仍然将User实例放回收集列表中?

Bonus: What if the thing I wanted to sort on were two levels deep, such as User.getProfile().getUsername() ?奖励:如果我想要排序的东西有两个深度,比如User.getProfile().getUsername()怎么办?

What you want is Comparator#comparing :你想要的是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
)

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));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM