首页 > 解决方案 > 使用流 java 8 或在 SQL 中对类进行分组,无论哪个最好

问题描述

数据是这样的

    head child assigned total
[   Mas   Mas1     2    5
,   Mas   Mas2     0    5
,   Usr   usr1     4    4
,   Usr   usr2     1    3
,   Inv   Inv1     3    5
,   Inv   Inv2     2    3
,   Inv   Inv3     2    3
,   Inv   Inv4     1    3
]

我想要一个特定标题的孩子的总和。

我在sql中使用分区

select head,
SUM(childAssigned) over (partition by am.acl_group) as assignedHead,
sum(childTotal) over (partition by am.acl_group) as totalHead,
child,
childAssigned,
childTotal

由于 HQL astquerytranslatorfactory 不支持“分区依据”,因此我将其用作本机查询

我有一个持有 SQL 响应的类

class AclList{
    String head;
    Integer assignedHead;
    Integer totalHead;
    String child;
    Integer assignedChild;
    Integer totalChild;
}

数据是这样的

[   Mas 2   10  Mas1    2   5
,   Mas 2   10  Mas2    0   5
,   Usr 5   7   usr1    4   4
,   Usr 5   7   usr2    1   3
,   Inv 8   14  Inv1    3   5
,   Inv 8   14  Inv2    2   3
,   Inv 8   14  Inv3    2   3
,   Inv 8   14  Inv4    1   3
]

我想要一个响应,它将分组相同标题的孩子。

响应应该像 ResponseClass(type,assigned,total,List)

[ 
  { 
    "type":"MAS",
    "assigned":"2",
    "total":"10",
    "subType":[ 
      { 
        "type":"MAS1",
        "assigned":"2",
        "total":"5"
      },
      { 
        "type":"MAS2",
        "assigned":"0",
        "total":"5"
      }
    ]
  },
  { 
    "type":"USR",
    "assigned":"5",
    "total":"7",
    "subType":[ 
      { 
        "type":"USR1",
        "assigned":"4",
        "total":"4"
      },
      { 
        "type":"USR2",
        "assigned":"1",
        "total":"3"
      }
    ]
  }
]

class Details(type,assigned,total) 我的方法是在 hashmap 的 key 中保留 header,在 hashmap 的 value 中保留 child 由于 head 的所有 3 列都是相同的,所以,equals,hashcode 小心。

类 ChildDetails(List) HashMap

Iterate sql response
if hashmap.contains(head) //exist
    fetch value, add new one in list
    hashmap.put(head, updated)
else
    create header,
    create child, add it to a blank list
    hashmap.put(head, new list)

再次迭代 hashmap,将其排列在新的 json 响应中

但是,这是一个繁琐的过程和低效的。

无论如何它可以用 JAVA stream() 来完成吗?

标签: javasqljava-stream

解决方案


Collectors.groupingByCollector可以在这里为您提供帮助。

设置:

// original data AclList
class AclList {

  String head;
  Integer assignedHead;
  Integer totalHead;
  String child;
  Integer assignedChild;
  Integer totalChild;
}

// Subtype in the response object based on Json
class SubType {

  String type;
  Integer assigned;
  Integer total;

  public SubType(String type, Integer assigned, Integer total) {
    this.type = type;
    this.assigned = assigned;
    this.total = total;
  }
}

// Response object based on Json
class Response {

  String type;
  Integer assigned;
  Integer total;
  List<SubType> subType;

  public Response(String type, Integer assigned, Integer total, List<SubType> subType) {
    this.type = type;
    this.assigned = assigned;
    this.total = total;
    this.subType = subType;
  }
}

步骤 1:head按类中的字段对数据进行分组AclList。此步骤返回一个Map不同的head值作为键,并返回一个AclList对象列表作为值,按键分组。

Map<String, List<AclList>> groupedByHead = data
    .stream()
    .collect(Collectors.groupingBy(acl -> acl.head));

第 2 步:只需操作Map即可创建所需的响应结构。

List<Response> response = groupedByHead.entrySet()
    .stream()
    .filter(e -> e.getValue().size() > 0)
    .map(e -> {
          List<AclList> acls = e.getValue();
          AclList first = acls.get(0);
          List<SubType> children = acls
              .stream()
              .map(acl -> new SubType(acl.child, acl.assignedChild, acl.totalChild))
              .collect(Collectors.toList());

          return new Response(first.head, first.assignedHead, first.totalHead, children);
    })
    .collect(Collectors.toList());

注意:我不确定您的约束,但最好只在数据库查询中进行分组操作,而不是在代码中进行。


推荐阅读