java 8 流 groupingBy 到自定义对象的集合
java 8 stream groupingBy into collection of custom object
我有以下class结构
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”中。是否可以在单个 operation/iteration 中完成?
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));
由于 masterStoreId
和 operatorIdentifier
在组中相同(已在评论中确认),您可以通过使用 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())));
为了完成实施,您正在尝试。您需要确保 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));
我有以下class结构
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));
由于 masterStoreId
和 operatorIdentifier
在组中相同(已在评论中确认),您可以通过使用 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())));
为了完成实施,您正在尝试。您需要确保 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));