我有两套角色。一个来自数据库,另一个来自UI。我还根据角色的名称编写了两个角色的比较方法。
问题:如果比较值使用lambdas表达式返回true,我想提取角色(保留数据库中的一个)。
matchingRoleNames
效果很好,但我没有寻找最好的lambdas做法,而没有循环。
这是我的设定结果,工作正常:
Set<Role> rolesFromUI = user.getRolesFromUI();
Stream <Role> roleStreamFromDB = roleService.getAllRolesStreamFromDatabase();
Set<Role> matchingRoleNames = roleStreamFromDB.filter(role->
{
for(Role roleTmp:rolesFromUI){
if(roleTmp.compareTo(role)==0){
return true;
}
}
return false;
})
public int compareTo(Role role){
return this.roleName.compareTo(role.getRoleName());
}
谢谢
答案 0 :(得分:1)
而不是在第一个流的filter
中间操作中使用for each循环,您可以只流过另一个集合,看看其中的任何元素是否与第一个流的任何元素匹配。
即:
Set<Role> matchingRoleNames = roleStreamFromDB.filter(e -> rolesFromUI.stream().anyMatch( x -> x.compareTo(e) == 0))
.collect(Collectors.toSet());
答案 1 :(得分:1)
正如您所说,您希望按名称比较角色,您可以通过首先将UI角色的名称收集到Set
来执行您想要的操作,然后在过滤数据库角色时,只需检查是否当前角色的名称位于集合中:
// Collect UI role names
Set<String> uiRoleNames = user.getRolesFromUI().stream()
.map(Role::getRoleName)
.collect(Collectors.toSet());
// Filter DB roles
Set<Role> filteredRoles = roleService.getAllRolesStreamFromDatabase()
.filter(role -> uiRoleNames.contains(role.getRoleName()))
.collect(Collectors.toSet());
这既简单又有效,因为Set
返回的Collectors.toSet()
预计会有效查找(这意味着其contains
方法将为O(1)
平均情况)。
如果您想100%确定O(1)
的返回集合为contains
,您可以按如下方式收集UI角色名称:
Set<String> uiRoleNames = user.getRolesFromUI().stream()
.map(Role::getRoleName)
.collect(Collectors.toCollection(HashSet::new));