我开始使用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;
}
现在我进行查询并得到一个平坦的结果列表,例如:
[1, "moderator", 2014]
[1, "moderator", 2015]
[1, "dev", 2014]
[2, "dev", 2010]
[2, "dev", 2011]
[2, "dev", 2012]
1和2是userId。
我尝试了各种结构,但最后它比流利的更复杂。并没有工作:) 我在Java 8的书中读过它简单的#34;用收藏家建造dompain对象 当我读到这个时,我哭了一下:&#39;(
我试过
sb.collect(
collectingAndThen(
groupingBy(
Mybean::getUserId,
collectingAndThen(
groupingBy(Monbean::getPermissionId, mapping(convertPermission, toList())),
finisherFonction)
),
convertUser)
);
并且有一个地狱编译失败的地狱。
因为最后我想摆脱Map并获得List<User>
结果(我想我可以在entrySet上添加一个map调用来完成转换)。
答案 0 :(得分:6)
让我为您提供一些选择,然后您决定哪种看起来最清楚。我假设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());
选项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());
选项3:首先将bean滚动到userid的映射中,以将permissionid映射到年份列表(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());
答案 1 :(得分:2)
collectingAndThen
组合器是为累积的中间形式与所需的最终形式不同而设计的。这是joining()
收集器的情况(中间形式为StringBuilder
,但最终形式为String
),也可用于使用不可变包装器包装可变集合收集完成后。所以我不认为这是你正在寻找的工具。
如果您正在寻找“用户权限”,那么这将解决问题:
Map<UserId, List<Permission>>
queryResults.stream()
.collect(qr -> qr.getId(),
mapping(qr -> qr.getPermission() + ":" + qr.getDate(),
toList()));
这将导致:
1 -> [ moderator:2014, moderator:2015, dev:2014 ]
2 -> [ dev:2010, dev:2011, dev:2012 ]
这个想法是:
- 您按“id”分组(查询的第一个字段)
- 对于每条记录,您选择其余字段的某些功能(这里,为了清楚起见,我使用字符串连接,但您可以创建一个持有权限和年份的对象),并将 发送到下游收集器
- 使用Collectors.toList()作为下游收集器,然后它将是Map
创建的groupingBy
的“值”。