如何在流中形成项目列表?
How to form a list of items inside the stream?
下面来自我的数据库:
CD_STORE| CD_PRODUCT | LAST_PURCHASE |
4077 | 63920 | 2018-12-05 00:00:00 |
7003 | 64520 | 2019-03-13 17:55:40 |
7003 | 76008 | 2013-06-22 00:00:00 |
我想查询 return 一个输出,其中对于每个商店代码,我有一个包含产品代码和最后购买日期的产品列表:
[
{
"storeCode": 7003,
"products": [
{
"productCode": 64520,
"lastPurchase": "2020-08-06"
},
{
"productCode": 76008,
"lastPurchase": "2018-12-21"
}
]
},
{
"storeCode": 4077,
"products": [
{
"productCode": 63920,
"lastPurchase": "2021-03-10"
}
]
}
]
请注意,在上面的 json 中,来自同一商店的产品(在本例中为 storeCode 7003)在同一对象中。但是我的代码产生了不同的输出,每个产品都表示为单独的一行,而不是按照我想要的方式在同一商店代码中分组:
[
{
"storeCode": 7003,
"products": [
{
"productCode": 64520,
"lastPurchase": "2020-08-06"
}
]
},
{
"storeCode": 7003,
"products": [
{
"productCode": 76008,
"lastPurchase": "2018-12-21"
}
]
},
{
"storeCode": 4077,
"products": [
{
"productCode": 63920,
"lastPurchase": "2021-03-10"
}
]
}
]
下面是我生成先前输出的代码。怎么了?为什么会这样?
我的类:
public class StorePurchaseView {
private Integer storeCode;
private Set<StorePurchaseItemsView> products;
}
public class StorePurchaseItemsView {
private Long productCode;
private LocalDate lastPurchase;
}
我的转换器:
public Set<StorePurchaseView> viewConvert(Collection<Tuple> list) {
return list
.stream()
.map(tuple -> StorePurchaseView.builder()
.storeCode(ofNullable(tuple.get("CD_STORE")).isPresent()
? Integer.parseInt(tuple.get("CD_STORE").toString())
: null)
.products(Set.of(StorePurchaseItemsView
.builder()
.productCode(ofNullable(tuple.get("CD_PRODUCT")).isPresent()
? Long.parseLong(tuple.get("CD_PRODUCT").toString())
: null)
.lastPurchase(buildLastPurchase(tuple))
.build()))
.build())
.collect(Collectors.toSet());
}
#Edit 1 -> 以下代码引发编译错误 Type mismatch: cannot convert from Map<Object,Set<Object>> to Map<Integer,Set<StoreRepurchaseItemsView>>
Map<Integer, Set<StoreRepurchaseItemsView>> itemsViewMap = list.stream()
.collect(Collectors.groupingBy(item -> Integer.parseInt(item.get("CD_STORE").toString()),
Collectors.mapping(item -> Long.parseLong(item.get("CD_PRODUCT").toString()),
Collectors.toSet())));
itemsViewMap.entrySet().stream()
.map(e -> StoreRepurchaseView.builder()
.storeCode(e.getKey())
.products(e.getValue())
.build())
.collect(Collectors.toList());
您可以在以下方向进行尝试:
在流式传输元组时,您需要使用基于 tuple.get("CD_STORE")
的 Collectors.groupingBy
作为分类器。这将使您朝着正确的方向前进,期望“来自同一商店的产品(在本例中为 storeCode 7003)在同一对象内”。因此,您可能会得到 Map<Integer, List<Tuple>>
。
由于默认实现分组结果到具有身份元素的 toList
下游,作为下一步,您需要确保在之前将值转换为 StorePurchaseItemsView
收集它们。这可以通过指定 Collectors.mapping
下游来解决,例如 groupingBy(classifier, mapping(..., ...))
。您的转换将基于 tuple.get("CD_PRODUCT")
逻辑,映射的下游将是 toSet
.
按照上述步骤,您最终会创建一个 Map<Integer, Set<StorePurchaseItemsView>> storePurchaseViewMap
,因此作为最后一步,您可以将此 Map
的每个条目转换为您的实际 StorePurchaseView
对象并将它们收集到您选择的 Collection
中。这将遵循以下行:
storePurchaseViewMap.entrySet().stream()
.map(e -> StorePurchaseView.builder()
.storeCode(e.getKey())
.products(e.getValue())
.build()
)
.collect(Collectors.toList()); // or toCollection
我会将整体实施留给您,如有具体疑问,请随时使用可重现代码进行跟进。
下面来自我的数据库:
CD_STORE| CD_PRODUCT | LAST_PURCHASE |
4077 | 63920 | 2018-12-05 00:00:00 |
7003 | 64520 | 2019-03-13 17:55:40 |
7003 | 76008 | 2013-06-22 00:00:00 |
我想查询 return 一个输出,其中对于每个商店代码,我有一个包含产品代码和最后购买日期的产品列表:
[
{
"storeCode": 7003,
"products": [
{
"productCode": 64520,
"lastPurchase": "2020-08-06"
},
{
"productCode": 76008,
"lastPurchase": "2018-12-21"
}
]
},
{
"storeCode": 4077,
"products": [
{
"productCode": 63920,
"lastPurchase": "2021-03-10"
}
]
}
]
请注意,在上面的 json 中,来自同一商店的产品(在本例中为 storeCode 7003)在同一对象中。但是我的代码产生了不同的输出,每个产品都表示为单独的一行,而不是按照我想要的方式在同一商店代码中分组:
[
{
"storeCode": 7003,
"products": [
{
"productCode": 64520,
"lastPurchase": "2020-08-06"
}
]
},
{
"storeCode": 7003,
"products": [
{
"productCode": 76008,
"lastPurchase": "2018-12-21"
}
]
},
{
"storeCode": 4077,
"products": [
{
"productCode": 63920,
"lastPurchase": "2021-03-10"
}
]
}
]
下面是我生成先前输出的代码。怎么了?为什么会这样?
我的类:
public class StorePurchaseView {
private Integer storeCode;
private Set<StorePurchaseItemsView> products;
}
public class StorePurchaseItemsView {
private Long productCode;
private LocalDate lastPurchase;
}
我的转换器:
public Set<StorePurchaseView> viewConvert(Collection<Tuple> list) {
return list
.stream()
.map(tuple -> StorePurchaseView.builder()
.storeCode(ofNullable(tuple.get("CD_STORE")).isPresent()
? Integer.parseInt(tuple.get("CD_STORE").toString())
: null)
.products(Set.of(StorePurchaseItemsView
.builder()
.productCode(ofNullable(tuple.get("CD_PRODUCT")).isPresent()
? Long.parseLong(tuple.get("CD_PRODUCT").toString())
: null)
.lastPurchase(buildLastPurchase(tuple))
.build()))
.build())
.collect(Collectors.toSet());
}
#Edit 1 -> 以下代码引发编译错误 Type mismatch: cannot convert from Map<Object,Set<Object>> to Map<Integer,Set<StoreRepurchaseItemsView>>
Map<Integer, Set<StoreRepurchaseItemsView>> itemsViewMap = list.stream()
.collect(Collectors.groupingBy(item -> Integer.parseInt(item.get("CD_STORE").toString()),
Collectors.mapping(item -> Long.parseLong(item.get("CD_PRODUCT").toString()),
Collectors.toSet())));
itemsViewMap.entrySet().stream()
.map(e -> StoreRepurchaseView.builder()
.storeCode(e.getKey())
.products(e.getValue())
.build())
.collect(Collectors.toList());
您可以在以下方向进行尝试:
在流式传输元组时,您需要使用基于
tuple.get("CD_STORE")
的Collectors.groupingBy
作为分类器。这将使您朝着正确的方向前进,期望“来自同一商店的产品(在本例中为 storeCode 7003)在同一对象内”。因此,您可能会得到Map<Integer, List<Tuple>>
。由于默认实现分组结果到具有身份元素的
toList
下游,作为下一步,您需要确保在之前将值转换为StorePurchaseItemsView
收集它们。这可以通过指定Collectors.mapping
下游来解决,例如groupingBy(classifier, mapping(..., ...))
。您的转换将基于tuple.get("CD_PRODUCT")
逻辑,映射的下游将是toSet
.按照上述步骤,您最终会创建一个
Map<Integer, Set<StorePurchaseItemsView>> storePurchaseViewMap
,因此作为最后一步,您可以将此Map
的每个条目转换为您的实际StorePurchaseView
对象并将它们收集到您选择的Collection
中。这将遵循以下行:storePurchaseViewMap.entrySet().stream() .map(e -> StorePurchaseView.builder() .storeCode(e.getKey()) .products(e.getValue()) .build() ) .collect(Collectors.toList()); // or toCollection
我会将整体实施留给您,如有具体疑问,请随时使用可重现代码进行跟进。