【问题标题】:java 8 stream groupingBy into collection of custom objectjava 8流groupingBy进入自定义对象的集合
【发布时间】:2021-01-08 16:38:50
【问题描述】:

我有以下类结构


public class Store {
    private Long storeId;

    private Long masterStoreId;

    private String operatorIdentifier;
}

public class StoreInfo {

    private String operatorIdentifier;

    private Set<Long> slaveStoreIds;

    public StoreInfo(String operatorIdentifier, Set<Long> slaveStoreIds) {
        super();
        this.operatorIdentifier = operatorIdentifier;
        this.slaveStoreIds = slaveStoreIds;
    }

}

我想将“List”中。是否可以在单个操作/迭代中这样做?

List<Store> stores;

Map<Long, Set<Long>> slaveStoresAgainstMasterStore = stores.stream().collect(Collectors
                .groupingBy(Store::getMasterStoreId, Collectors.mapping(Store::getStoreId, Collectors.toSet())));

Map<Long, StoreInfo> storeInfoAgainstMasterStore = stores.stream()
                .collect(
                        Collectors
                                .toMap(Store::getMasterStoreId,
                                        val -> new StoreInfo(val.getOperatorIdentifier(),
                                                slaveStoresAgainstMasterStore.get(val.getMasterStoreId())),
                                        (a1, a2) -> a1));


【问题讨论】:

  • 您真的想要Map&lt;Long, StoreInfo&gt; 还是只想要List&lt;StoreInfo&gt; 对您有用? .. 你需要弄清楚(a1, a2) -&gt; a1 做了什么并将其替换为你打算执行的操作。
  • @Naman 我不想要List&lt;StoreInfo&gt;。我想在自定义 StoreInfo 对象中针对 masterStoreId 收集 storeId 列表。
  • masterStoreId 相同的 operatorIdentifier 相同?
  • @Rono 是的,masterStoreId 和 operatorIdentifier 是一样的

标签: java java-8 java-stream collectors


【解决方案1】:

由于masterStoreIdoperatorIdentifier 在组中相同(已在评论中确认),您可以通过使用AbstractMap.SimpleEntry 创建它们对来进行分组。然后使用Collectors.toMap 创建地图。

Map<Long, StoreInfo> storeInfoMap = 
    stores.stream()
          .collect(Collectors.groupingBy(
                      e -> new AbstractMap.SimpleEntry<>(e.getMasterStoreId(),
                                                        e.getOperatorIdentifier()),
                      Collectors.mapping(Store::getStoreId, Collectors.toSet())))
          .entrySet()
          .stream()
          .collect(Collectors.toMap(e -> e.getKey().getKey(),
                            e -> new StoreInfo(e.getKey().getValue(), e.getValue())));

【讨论】:

    【解决方案2】:

    为了完成实施,您正在尝试。您需要确保StoreInfo 内的合并能力,例如:

    public StoreInfo(String operatorIdentifier, Long slaveStoreId) {
        this.operatorIdentifier = operatorIdentifier;
        this.slaveStoreIds = new HashSet<>();
        this.slaveStoreIds.add(slaveStoreId);
    }
    
    public static StoreInfo mergeStoreInfo(StoreInfo storeInfo1, StoreInfo storeInfo2) {
        Set<Long> slaveIds = storeInfo1.getSlaveStoreIds();
        slaveIds.addAll(storeInfo2.getSlaveStoreIds());
        return new StoreInfo(storeInfo1.getOperatorIdentifier(), slaveIds);
    }
    

    这将简化收集器的实现,您可以相应地调用它们:

    Map<Long, StoreInfo> storeInfoAgainstMasterStore = stores.stream()
            .collect(Collectors.toMap(Store::getMasterStoreId,
                    store -> new StoreInfo(store.getOperatorIdentifier(), store.getStoreId()),
                    StoreInfo::mergeStoreInfo));
    

    【讨论】:

      猜你喜欢
      • 2017-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-30
      相关资源
      最近更新 更多