如何在流中形成项目列表?

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());

您可以在以下方向进行尝试:

  1. 在流式传输元组时,您需要使用基于 tuple.get("CD_STORE")Collectors.groupingBy 作为分类器。这将使您朝着正确的方向前进,期望“来自同一商店的产品(在本例中为 storeCode 7003)在同一对象内”。因此,您可能会得到 Map<Integer, List<Tuple>>

  2. 由于默认实现分组结果到具有身份元素的 toList 下游,作为下一步,您需要确保在之前将值转换为 StorePurchaseItemsView收集它们。这可以通过指定 Collectors.mapping 下游来解决,例如 groupingBy(classifier, mapping(..., ...))。您的转换将基于 tuple.get("CD_PRODUCT") 逻辑,映射的下游将是 toSet.

  3. 按照上述步骤,您最终会创建一个 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
    

我会将整体实施留给您,如有具体疑问,请随时使用可重现代码进行跟进。