如何按两个字段对对象列表进行分组并获取结果类型的对象列表
How to Group a List of objects by Two fields and obtain a List of objects of resulting type
我有一个 列表 如下所示的对象:
public class AssignDTO {
private String assignmentIbanId;
private String agreementFileId;
private BankData bankData;
// getter and setter
}
[
{
"assignmentIbanId":"6146dd87-2344-4149-9396-8e8a88493dd6",
"agreementFileId":"36de8604-ae56-49b3-b972-8071b459bf82",
"bankData": { "useType" : "a" }
},
{
"assignmentIbanId":"44cb8cc6-fe28-4e44-a78c-48a908795f38",
"agreementFileId":"854f0c37-b9d8-4533-9c02-0c1b64a909bd",
"bankData": { "useType" : "b" }
},
{
"assignmentIbanId":"44cb8cc6-fe28-4e44-a78c-48a908795f38",
"agreementFileId":"854f0c37-b9d8-4533-9c02-0c1b64a909bd",
"bankData": { "useType" : "c" }
}
]
如何按 agreementFileId
和 agreementFileId
字段对列表进行分组,如下所示
public class ResultDTO {
private String assignmentIbanId;
private String agreementFileId;
private Set<BankData> bankAccounts;
// getter and setter
}
[
{
"assignmentIbanId":"6146dd87-2344-4149-9396-8e8a88493dd6",
"agreementFileId":"36de8604-ae56-49b3-b972-8071b459bf82",
"bankAccounts": [{ "useType" : "a" }]
}
{
"assignmentIbanId":"44cb8cc6-fe28-4e44-a78c-48a908795f38",
"agreementFileId":"854f0c37-b9d8-4533-9c02-0c1b64a909bd",
"bankAccounts": [{ "useType" : "b" }, { "useType" : "c" }]
}
]
了解所需的 return 类型会有所帮助。这里有两个可能的解决方案:
Map<String, Map<String, List<AssignDTO>>> collect = list.stream().collect(
Collectors.groupingBy(AssignIbanEntityDTO::getAgreementFileId,
Collectors.groupingBy(AssignDTO::getBankData)));
结构:
{ "a" -> { "b" -> [obj1, obj2] } }
另一种选择是:
Map<List<String>, List<AssignDTO>> collect = list.stream().collect(
Collectors.groupingBy(dto -> List.of(dto.getAgreementFileId(), dto.getBankData()));
结构:
{ ["a", "b"] -> [obj1, obj2] }
没有其他信息,很难判断选择哪个。
作为第一步,您可以创建一个 嵌套映射 应用 Collector.groupingBy()
两次,或者使用能够携带两个值的对象对数据进行分组, 就像 Map.Entry
, 作为 key.
在这两种情况下,mapping()
和 toSet()
的组合作为下游收集器会很方便:
Collectors.mapping(AssignDTO::getBankData, Collectors.toSet()
因此,它会生成一个以 Set<BankData>
作为值的中间映射。
然后在条目集上创建一个流并应用 map()
将每个条目变成 ResultDTO
并将结果收集到列表中 toList()
(Java 16+) 或利用 Collectors.toList()
.
这就是它的样子(Java-8 的地图条目示例):
public static void main(String[] args) {
List<AssignDTO> source =
List.of(new AssignDTO("6146dd87-2344-4149-9396-8e8a88493dd6",
"36de8604-ae56-49b3-b972-8071b459bf82", new BankData("a")),
new AssignDTO("44cb8cc6-fe28-4e44-a78c-48a908795f38",
"854f0c37-b9d8-4533-9c02-0c1b64a909bd", new BankData("b")),
new AssignDTO("44cb8cc6-fe28-4e44-a78c-48a908795f38",
"854f0c37-b9d8-4533-9c02-0c1b64a909bd", new BankData("c")));
List<ResultDTO> result =
source.stream()
.collect(Collectors.groupingBy(assignDTO -> new AbstractMap.SimpleEntry<>(assignDTO.getAgreementFileId(), assignDTO.getAgreementFileId()),
Collectors.mapping(AssignDTO::getBankData, Collectors.toSet()))) // creating an intermediate map `Map<Map.Entry<String, String>>, Set<BankData>>
.entrySet().stream()
.map(entry -> new ResultDTO(entry.getKey().getKey(),
entry.getKey().getValue(),
entry.getValue()))
.collect(Collectors.toList());
result.forEach(System.out::println);
}
输出
ResultDTO{
assignmentIbanId : '854f0c37-b9d8-4533-9c02-0c1b64a909bd',
agreementFileId : '854f0c37-b9d8-4533-9c02-0c1b64a909bd',
bankAccounts : [{useType : 'b'}, {useType : 'c'}]}
ResultDTO{
assignmentIbanId : '36de8604-ae56-49b3-b972-8071b459bf82',
agreementFileId : '36de8604-ae56-49b3-b972-8071b459bf82',
bankAccounts : [{useType : 'a'}]}
我有一个 列表 如下所示的对象:
public class AssignDTO {
private String assignmentIbanId;
private String agreementFileId;
private BankData bankData;
// getter and setter
}
[
{
"assignmentIbanId":"6146dd87-2344-4149-9396-8e8a88493dd6",
"agreementFileId":"36de8604-ae56-49b3-b972-8071b459bf82",
"bankData": { "useType" : "a" }
},
{
"assignmentIbanId":"44cb8cc6-fe28-4e44-a78c-48a908795f38",
"agreementFileId":"854f0c37-b9d8-4533-9c02-0c1b64a909bd",
"bankData": { "useType" : "b" }
},
{
"assignmentIbanId":"44cb8cc6-fe28-4e44-a78c-48a908795f38",
"agreementFileId":"854f0c37-b9d8-4533-9c02-0c1b64a909bd",
"bankData": { "useType" : "c" }
}
]
如何按 agreementFileId
和 agreementFileId
字段对列表进行分组,如下所示
public class ResultDTO {
private String assignmentIbanId;
private String agreementFileId;
private Set<BankData> bankAccounts;
// getter and setter
}
[
{
"assignmentIbanId":"6146dd87-2344-4149-9396-8e8a88493dd6",
"agreementFileId":"36de8604-ae56-49b3-b972-8071b459bf82",
"bankAccounts": [{ "useType" : "a" }]
}
{
"assignmentIbanId":"44cb8cc6-fe28-4e44-a78c-48a908795f38",
"agreementFileId":"854f0c37-b9d8-4533-9c02-0c1b64a909bd",
"bankAccounts": [{ "useType" : "b" }, { "useType" : "c" }]
}
]
了解所需的 return 类型会有所帮助。这里有两个可能的解决方案:
Map<String, Map<String, List<AssignDTO>>> collect = list.stream().collect(
Collectors.groupingBy(AssignIbanEntityDTO::getAgreementFileId,
Collectors.groupingBy(AssignDTO::getBankData)));
结构:
{ "a" -> { "b" -> [obj1, obj2] } }
另一种选择是:
Map<List<String>, List<AssignDTO>> collect = list.stream().collect(
Collectors.groupingBy(dto -> List.of(dto.getAgreementFileId(), dto.getBankData()));
结构:
{ ["a", "b"] -> [obj1, obj2] }
没有其他信息,很难判断选择哪个。
作为第一步,您可以创建一个 嵌套映射 应用 Collector.groupingBy()
两次,或者使用能够携带两个值的对象对数据进行分组, 就像 Map.Entry
, 作为 key.
在这两种情况下,mapping()
和 toSet()
的组合作为下游收集器会很方便:
Collectors.mapping(AssignDTO::getBankData, Collectors.toSet()
因此,它会生成一个以 Set<BankData>
作为值的中间映射。
然后在条目集上创建一个流并应用 map()
将每个条目变成 ResultDTO
并将结果收集到列表中 toList()
(Java 16+) 或利用 Collectors.toList()
.
这就是它的样子(Java-8 的地图条目示例):
public static void main(String[] args) {
List<AssignDTO> source =
List.of(new AssignDTO("6146dd87-2344-4149-9396-8e8a88493dd6",
"36de8604-ae56-49b3-b972-8071b459bf82", new BankData("a")),
new AssignDTO("44cb8cc6-fe28-4e44-a78c-48a908795f38",
"854f0c37-b9d8-4533-9c02-0c1b64a909bd", new BankData("b")),
new AssignDTO("44cb8cc6-fe28-4e44-a78c-48a908795f38",
"854f0c37-b9d8-4533-9c02-0c1b64a909bd", new BankData("c")));
List<ResultDTO> result =
source.stream()
.collect(Collectors.groupingBy(assignDTO -> new AbstractMap.SimpleEntry<>(assignDTO.getAgreementFileId(), assignDTO.getAgreementFileId()),
Collectors.mapping(AssignDTO::getBankData, Collectors.toSet()))) // creating an intermediate map `Map<Map.Entry<String, String>>, Set<BankData>>
.entrySet().stream()
.map(entry -> new ResultDTO(entry.getKey().getKey(),
entry.getKey().getValue(),
entry.getValue()))
.collect(Collectors.toList());
result.forEach(System.out::println);
}
输出
ResultDTO{
assignmentIbanId : '854f0c37-b9d8-4533-9c02-0c1b64a909bd',
agreementFileId : '854f0c37-b9d8-4533-9c02-0c1b64a909bd',
bankAccounts : [{useType : 'b'}, {useType : 'c'}]}
ResultDTO{
assignmentIbanId : '36de8604-ae56-49b3-b972-8071b459bf82',
agreementFileId : '36de8604-ae56-49b3-b972-8071b459bf82',
bankAccounts : [{useType : 'a'}]}