如何将多个集合的结构展平为一个具有通用 ID 和流的集合
How to flatten the structure of multiple collections into a single one with a common id with streams
假设我有一个 dto 列表,例如:
@Builder(setterPrefix = "with")
@Data
public class ListWithDetailsRow {
String name;
LocalDateTime updatedAt;
LocalDateTime createdAt;
String customerId;
String listId;
String productName;
String productId;
Integer quantity;
LocalDateTime addedAt;
}
我想将上面的映射到:
@Builder
@Getter
@Setter
@RequiredArgsConstructor
public class ListDetails {
private final String name;
private final String listId;
private final String customerId;
private final LocalDateTime createdAt;
private final LocalDateTime updatedAt;
private final List<ListProductDetails> products;
}
其中 ListProductDetails 看起来像:
@RequiredArgsConstructor
@Builder
@Getter
@Setter
public class ListProductDetails {
private final String productId;
private final Integer quantity;
private final LocalDateTime addedAt;
}
到目前为止我有:
public List<ListDetails> groupListWithProductsById1(List<ListWithDetailsRow> listWithDetailsRows) {
return listWithDetailsRows.stream()
.collect(Collectors.groupingBy(ListWithDetailsRow::getListId))
.values()
.stream()
.flatMap(Collection::stream)
.map(sl -> new ListDetails(
sl.getName(),
sl.getListId(),
sl.getCustomerId(),
sl.getCreatedAt(),
sl.getUpdatedAt(),
newArrayList(
new ListProductDetails(
sl.getProductId(),
sl.getQuantity(),
sl.getAddedAt()))))
.collect(Collectors.toList());
但是通过这个实现,我收到了 ListDetails 列表 class
但目标是接收具有扁平化产品结构的列表,因为它们具有相同的 ID 组。
我知道我可以使用以下方法扁平化这个产品结构:
listDetails.stream().flatMap(sl -> sl.getProducts().stream()).collect(Collectors.toList())
但不知道groupingBy()
操作后如何正确使用。将不胜感激您的建议。干杯!
如果我没理解错的话,你想做的是:
public List<ListDetails> groupListWithProductsById1(List<ListWithDetailsRow> listWithDetailsRows) {
return listWithDetailsRows.stream()
.collect(Collectors.groupingBy(ListWithDetailsRow::getListId)).values().stream()
.map(rows ->
new ListDetails(
rows.get(0).getName(),
rows.get(0).getListId(),
rows.get(0).getCustomerId(),
rows.get(0).getCreatedAt(),
rows.get(0).getUpdatedAt(),
rows.stream().map(row -> new ListProductDetails(
row.getProductId(), row.getQuantity(), row.getAddedAt()
)).collect(Collectors.toList())
)
).collect(Collectors.toList());
}
按列表 ID 分组后,您有一个 Collection<List<ListWithDetailsRow>>
作为返回地图的 values()
。集合中的每个列表代表一个组。
然后你可以map
每组一个ListDetails
。 name
、listId
、customerId
、createdAt
和 updatedAt
字段 ListDetails
可以取自组中的任意元素(我我选择了第一个),因为每个元素对于这些字段都应该具有相同的值。
对于 products
字段,只需 map
ListWithDetailsRow
到 ListProductDetails
并收集到列表中。
假设我有一个 dto 列表,例如:
@Builder(setterPrefix = "with")
@Data
public class ListWithDetailsRow {
String name;
LocalDateTime updatedAt;
LocalDateTime createdAt;
String customerId;
String listId;
String productName;
String productId;
Integer quantity;
LocalDateTime addedAt;
}
我想将上面的映射到:
@Builder
@Getter
@Setter
@RequiredArgsConstructor
public class ListDetails {
private final String name;
private final String listId;
private final String customerId;
private final LocalDateTime createdAt;
private final LocalDateTime updatedAt;
private final List<ListProductDetails> products;
}
其中 ListProductDetails 看起来像:
@RequiredArgsConstructor
@Builder
@Getter
@Setter
public class ListProductDetails {
private final String productId;
private final Integer quantity;
private final LocalDateTime addedAt;
}
到目前为止我有:
public List<ListDetails> groupListWithProductsById1(List<ListWithDetailsRow> listWithDetailsRows) {
return listWithDetailsRows.stream()
.collect(Collectors.groupingBy(ListWithDetailsRow::getListId))
.values()
.stream()
.flatMap(Collection::stream)
.map(sl -> new ListDetails(
sl.getName(),
sl.getListId(),
sl.getCustomerId(),
sl.getCreatedAt(),
sl.getUpdatedAt(),
newArrayList(
new ListProductDetails(
sl.getProductId(),
sl.getQuantity(),
sl.getAddedAt()))))
.collect(Collectors.toList());
但是通过这个实现,我收到了 ListDetails 列表 class
但目标是接收具有扁平化产品结构的列表,因为它们具有相同的 ID 组。 我知道我可以使用以下方法扁平化这个产品结构:
listDetails.stream().flatMap(sl -> sl.getProducts().stream()).collect(Collectors.toList())
但不知道groupingBy()
操作后如何正确使用。将不胜感激您的建议。干杯!
如果我没理解错的话,你想做的是:
public List<ListDetails> groupListWithProductsById1(List<ListWithDetailsRow> listWithDetailsRows) {
return listWithDetailsRows.stream()
.collect(Collectors.groupingBy(ListWithDetailsRow::getListId)).values().stream()
.map(rows ->
new ListDetails(
rows.get(0).getName(),
rows.get(0).getListId(),
rows.get(0).getCustomerId(),
rows.get(0).getCreatedAt(),
rows.get(0).getUpdatedAt(),
rows.stream().map(row -> new ListProductDetails(
row.getProductId(), row.getQuantity(), row.getAddedAt()
)).collect(Collectors.toList())
)
).collect(Collectors.toList());
}
按列表 ID 分组后,您有一个 Collection<List<ListWithDetailsRow>>
作为返回地图的 values()
。集合中的每个列表代表一个组。
然后你可以map
每组一个ListDetails
。 name
、listId
、customerId
、createdAt
和 updatedAt
字段 ListDetails
可以取自组中的任意元素(我我选择了第一个),因为每个元素对于这些字段都应该具有相同的值。
对于 products
字段,只需 map
ListWithDetailsRow
到 ListProductDetails
并收集到列表中。