Java 8 Streams:构建多级/复合对象

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)

并得到一个地狱编译失败的地狱.

  • 使用java 8流构建多级复合域对象的最佳方法是什么?
  • 收藏和陈/终结者是一个好主意?
  • 或者你只使用groupingBy后跟一个映射函数?
  • 你将分类器转换为一个对象(一级第一级映射函数?)

因为最后我想摆脱Map并得到一个List<User>结果(我想我可以在entrySet上添加一个map调用来完成转换).

Mis*_*sha 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());
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)