Arc*_*nge 6 java java-8 java-stream collectors
我开始使用java 8流API.我想将"sql结果集"列表转换为域对象,即复合结构.
域对象:用户拥有一组权限,每个权限都有一年的应用程序集合.例如,John有2个权限(MODERATOR和DEV).其主持人许可仅适用于2014年和2015年,其开发许可仅适用于2014年.
class User {
// some primitives attributes
List<Permission> permission;
}
class Permission {
// some primitives attributes
List<Integer> years;
}
Run Code Online (Sandbox Code Playgroud)
现在我进行查询并得到一个平坦的结果列表,如:
[1, "moderator", 2014]
[1, "moderator", 2015]
[1, "dev", 2014]
[2, "dev", 2010]
[2, "dev", 2011]
[2, "dev", 2012]
Run Code Online (Sandbox Code Playgroud)
1和2是userId.
我尝试了各种结构,但最后它比流畅更复杂.并没有工作:)
我在Java 8书中读到,用收集器构建dompain对象是"简单的".
当我读到这个时,我哭了一下:'(
我试过了
sb.collect(
collectingAndThen(
groupingBy(
Mybean::getUserId,
collectingAndThen(
groupingBy(Monbean::getPermissionId, mapping(convertPermission, toList())),
finisherFonction)
),
convertUser)
);
Run Code Online (Sandbox Code Playgroud)
并得到一个地狱编译失败的地狱.
因为最后我想摆脱Map并得到一个List<User>结果(我想我可以在entrySet上添加一个map调用来完成转换).
让我为您提供一些选择,您可以决定哪种看起来最清楚.我假设User构造函数是User(int userId, List<Permission> permissions)和Permission构造函数是Permission(String permissionId, List<Integer> years)
方案1:直接方法.按用户ID分组,构造每个用户标识的权限列表并创建用户对象.就个人而言,我觉得这很多在收藏家中筑巢很难遵循.
List<User> users = beans.stream()
.collect(
groupingBy(
MyBean::getUserid,
collectingAndThen(
groupingBy(
MyBean::getPermission,
mapping(MyBean::getYear, toList())
),
t -> t.entrySet().stream()
.map(e -> new Permission(e.getKey(), e.getValue()))
.collect(toList())
)
)
).entrySet().stream()
.map(e -> new User(e.getKey(), e.getValue()))
.collect(toList());
Run Code Online (Sandbox Code Playgroud)
选项2:与上述相同,但为了清楚起见,单独制作许可收集者.
Collector<MyBean, ?, List<Permission>> collectPermissions = collectingAndThen(
groupingBy(MyBean::getPermission, mapping(MyBean::getYear, toList())),
t -> t.entrySet().stream()
.map(e -> new Permission(e.getKey(), e.getValue()))
.collect(toList())
);
List<User> users = beans.stream()
.collect(groupingBy(MyBean::getUserid, collectPermissions))
.entrySet().stream()
.map(e -> new User(e.getKey(), e.getValue()))
.collect(toList());
Run Code Online (Sandbox Code Playgroud)
选项3:首先将bean滚动到userid的映射中,以将permissionid映射到years(Map<Integer, Map<String, List<Integer>>)列表.然后从地图中构造域对象
List<User> users = beans.stream().collect(
groupingBy(
MyBean::getUserid,
groupingBy(
MyBean::getPermission,
mapping(MyBean::getYear, toList())
)
)
).entrySet().stream()
.map(u -> new User(
u.getKey(),
u.getValue().entrySet().stream()
.map(p -> new Permission(p.getKey(), p.getValue()))
.collect(toList())
)
).collect(toList());
Run Code Online (Sandbox Code Playgroud)