在Java 8流中按属性排序

时间:2014-10-26 00:14:06

标签: java sorting lambda java-8 java-stream

哦,那些棘手的Java 8流与lambdas。它们非常强大,但错综复杂的方法需要将一个标题包裹起来。

我们说我的User类型带有属性User.getName()。我们假设我有一个与名称相关联的用户Map<String, User>的地图(例如,登录用户名)。让我们进一步说我有一个比较器UserNameComparator.INSTANCE的实例来排序用户名(可能还有花哨的合作者等)。

那么如何获取地图中的用户列表,按用户名排序?我可以忽略地图键并执行此操作:

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

但是,我必须提取名称以使用UserNameComparator.INSTANCE的那一行似乎是太多的手工工作。有没有什么方法可以简单地提供User::getName作为一些映射函数,仅用于排序,并且仍然将User实例返回到收集列表中?

奖励:如果我想要排序的东西有两个级别,例如User.getProfile().getUsername(),该怎么办?

2 个答案:

答案 0 :(得分:66)

你想要的是Comparator#comparing

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

对于问题的第二部分,您只需使用

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

答案 1 :(得分:0)

为了在第二级进行比较,您可以这样进行: 为对象

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