java - 使用流 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() 来完成吗?
解决方案
Collectors.groupingBy流Collector
可以在这里为您提供帮助。
设置:
// 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());
注意:我不确定您的约束,但最好只在数据库查询中进行分组操作,而不是在代码中进行。
推荐阅读
- wpf - 如何使用 AttachedCommandBehavior 将多个事件绑定到 setter 样式?
- web-config - ASP.NET 会话即将到期
- javascript - 是否可以通过使用 QuerySelectoAll 指定属性值范围来获取元素
- javascript - 在使用带有 discord.js 的谷歌自定义搜索时,我收到了 400 个错误请求!我在这里做错了什么?
- junit - 第一次失败后停止测试执行
- typescript - 可以使用 Typescript 从静态字符串(枚举或对象)中推断对象键
- java - 测试通过但未执行操作
- reactjs - 如何使用 MUI Datatable 使用值进行排序,而不是自定义正文渲染返回的内容?
- react-native - 反应原生链接依赖依赖
- asp.net-core - 仅针对特定 API 位置的 ASP.NET Core TLS 客户端证书身份验证