使用Comparator.comparing按照一个对象列表和第二个属性排序一个对象。

4

我最初通过对象的一个属性(比如说一个用户firstName)对列表进行排序,代码如下:

Collections.sort(userList, (u1, u2) -> (u1.getFirstName()).compareTo(u2.getFirstName()));

我能替换为以下内容:
Collections.sort(userList, Comparator.comparing(User::getFirstName));

但现在User有一个包含每个roleNameRole列表,我想按UserRoleroleName对列表进行排序。 我想到了这个:

Collections.sort(userList, (u1, u2) -> (u1.getUserRoles().get(0).getRoleName()).compareTo(u2.getUserRoles().get(0).getRoleName()));

这似乎运行正常。

在IDE中,现在有一条消息:可以使用Comparator.comparing替换...,但我不知道该如何准确地执行此操作。这是否可能?类似以下的内容无法正常工作:

Collections.sort(userList, Comparator.comparing(User::getUserRoles.get(0).getRoleName());

如何使用Comparator.comparing进行排序?

在按roleName排序后,如何按firstName作为第二属性进行排序?


1
你使用的是哪个集成开发环境(IDE)?当你在IntelliJ中看到这样的提示时,你可以直接按 alt + enter 键,它就会自动为你完成。 - Michael
1
不要觉得你必须采纳IDE提供的建议。如果你按照IDE的建议修改了代码(最好是让IDE自动完成修改),然后IDE又建议将其改回原来的样子,也不要太惊讶! - Kevin Anderson
1
根据Demeter法则,您不应该调用user.getUserRoles.get(0).getRoleName(),而是在User上实现一个getUserRoleName(或者是getUsersFirstRoleName)。然后您可以使用Comparator.comparing(...).thenComparing(...)链。鉴于用户可能根本没有角色,您还可以考虑使用Comparator.nullsLast / Comparator.nullsFirst。 - Michal
@Michal:我之前不知道这个,但是听起来很合理。如果用户有多个角色怎么办? - manu
@Michal:你能否提供一个避免使用Demeter法则的例子? - manu
显示剩余3条评论
1个回答

7

在这种情况下,您不能使用方法引用,但可以使用lambda表达式:

Collections.sort(userList, Comparator.comparing(u -> u.getUserRoles().get(0).getRoleName()));

按两个属性进行排序:
Collections.sort(userList, Comparator.comparing((Function<User,String>)u -> u.getUserRoles().get(0).getRoleName())
                                     .thenComparing(User::getFirstName));

或者

Collections.sort(userList, Comparator.comparing((User u) -> u.getUserRoles().get(0).getRoleName())
                                     .thenComparing(User::getFirstName));

谢谢。我不得不添加*()*:Collections.sort(userList, Comparator.comparing(u -> u.getUserRoles().get(0).getRoleName()));现在我正在努力使用thenComparing,因为我想按名字的首字母对列表进行排序。有什么解决方法吗? - manu
@Eran:按两个属性排序不起作用。它给了我“无法解析方法'getUserRoles()'”。 - manu
1
@manu 看起来编译器在类型推断方面存在一些问题。我尝试了类似的排序(不同元素),将 lambda 表达式强制转换为正确的类型似乎有所帮助。请参见编辑。 - Eran
1
这个可以运行。我现在首先按userRolesroleName排序,然后按lastName排序,最后按firstName排序,使用Collections.sort(userList, Comparator.comparing((Function<User, String>) u -> u.getUserRoles().get(0).getRoleName()).thenComparing(User::getLastName).thenComparing(User::getFirstName));。非常感谢! - manu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接