Java8如何根据另一个地图的值过滤地图

时间:2019-05-31 19:16:08

标签: java java-8 java-stream

我有3张地图,它们的设置如下:-

  //Map1 
  Map<CatalogCd, Set<ItemUID>> availableItems
  //Map2 
  Map<CatalogCd, FilteringPreferences> filteringPrefs
  //Map3 
  Map<ItemUID, ItemInformation> itemDetailInformation

我想做的是,

仔细检查availableItems,然后查看给定ItemUID的ItemInformation是否与首选项匹配(基本上通过某种谓词检查)。

如您所见,前两个映射具有相同的键,同一键的filterPrefs应用于该目录cd键的整个集合,所有不符合Preferences中谓词设置条件的对象都应从生成的itemuid的集合。

我有兴趣使用Java 8流,映射,过滤器方法使外观看起来更好,而不是传统的循环遍历一个映射,然后手动删除项目或将其添加到新结果映射中。

这是我得到的传统的for循环非java-8样式的代码。

public Map<CatalogCd, Set<ItemUID>> filterResponse(Map<CatalogCd, Set<ItemUID>> availableItems,  Map<CatalogCd, FilteringPreferences> filteringPrefs, Map<ItemUID, ItemInformation> itemDetailInformation)
{
    Map<CatalogCd, Set<ItemUID>> resultingFilteredItemsMap = new HashMap<>();
    for(Map.Entry<CatalogCd,FilteringPreferences> catalogCdEntry : filteringPrefs.entrySet()){
    CatalogCd catalogCdInRequest = catalogCdEntry.getKey();
    EnumSet<PrefA> prefA = catalogCdEntry.getValue().getSupportedPrefAs();

    //get set of items for this catalogcd, loop over each itemuid, check from itemDetailInformation map
    //to see if that itemuid's enumset has intersection with the enumset in request's preference.
    Set<ItemUID> itemsForThisCatalogCd = availableItems.get(catalogCdInRequest);
    for(ItemUID item:itemsForThisCatalogCd){
        EnumSet<PrefA> enumSetFromItemInfo = itemDetailInformation.get(item).getPrefAs();
        enumSetFromItemInfo.retainAll(prefA);
        if(!enumSetFromItemInfo.isEmpty()){
            if(resultingFilteredItemsMap.get(catalogCdInRequest)!=null){
                Set<ItemUID> items = resultingFilteredItemsMap.get(catalogCdInRequest);
                items.add(item);
                resultingFilteredItemsMap.put(catalogCdInRequest, items);
            }else{
                resultingFilteredItemsMap.put(catalogCdInRequest, Sets.newHashSet(item));
              }
           }
        }
    }
   return resultingFilteredItemsMap;
}

到目前为止,我尝试过的是:-

availableItems
    .entrySet() 
    .stream() 
    .filter(x- >predicateFilterFactory.createPredicateFilter(filteringPref.get(x.getKey()))) 
    .collect(Collectors.toMap(x->x.getKey(),x->x.getValue));

但是这表示谓词不能转换为布尔值另外,我不知道如何将实际的内容映射到其中。 任何帮助都会很棒。 谢谢

2 个答案:

答案 0 :(得分:1)

您在这里:

public Map<CatalogCd, Set<ItemUID>> filterResponse(Map<CatalogCd, Set<ItemUID>> availableItems,
        Map<CatalogCd, FilteringPreferences> filteringPrefs, Map<ItemUID, ItemInformation> itemDetailInformation) {
    Map<CatalogCd, Set<ItemUID>> resultingFilteredItemsMap = new HashMap<>();
    filteringPrefs.forEach((key, value) -> giveSuitableName(availableItems, itemDetailInformation,
            resultingFilteredItemsMap, key, value));
    return resultingFilteredItemsMap;
}

private void giveSuitableName(Map<CatalogCd, Set<ItemUID>> availableItems,
        Map<ItemUID, ItemInformation> itemDetailInformation, Map<CatalogCd, Set<ItemUID>> resultingFilteredItemsMap,
        CatalogCd catalogCdInRequest, FilteringPreferences filteringPreferences) {
    EnumSet<PrefA> prefA = filteringPreferences.getSupportedPrefAs();

    // get set of items for this catalogcd, loop over each itemuid, check from
    // itemDetailInformation map
    // to see if that itemuid's enumset has intersection with the enumset in
    // request's preference.
    availableItems.get(catalogCdInRequest).stream()
            .map(ai -> collectAndAddItems(itemDetailInformation, resultingFilteredItemsMap, catalogCdInRequest,
                    prefA, ai))
            .filter(s -> !s.isEmpty()).forEach(fs -> resultingFilteredItemsMap.put(catalogCdInRequest, fs));
}

private Set<ItemUID> collectAndAddItems(Map<ItemUID, ItemInformation> itemDetailInformation,
        Map<CatalogCd, Set<ItemUID>> resultingFilteredItemsMap, CatalogCd catalogCdInRequest, EnumSet<PrefA> prefA,
        ItemUID item) {
    EnumSet<PrefA> enumSetFromItemInfo = itemDetailInformation.get(item).getPrefAs();
    enumSetFromItemInfo.retainAll(prefA);
    Set<ItemUID> items = new HashSet<>();
    if (!enumSetFromItemInfo.isEmpty()) {
        if (resultingFilteredItemsMap.get(catalogCdInRequest) != null) {
            items = resultingFilteredItemsMap.get(catalogCdInRequest);
            items.add(item);
        } else {
            items = new HashSet<>(Arrays.asList(item));
        }
    }
    return items;
}

答案 1 :(得分:1)

此方法应该可以解决您的问题:

public static Map<CatalogCd, Set<ItemUID>> filterResponse(Map<CatalogCd, Set<ItemUID>> availableItems, 
            Map<CatalogCd, FilteringPreferences> filteringPrefs, Map<ItemUID, ItemInformation> itemDetailInformation) {
    return filteringPrefs.entrySet().stream()
            .flatMap(e -> availableItems.getOrDefault(e.getKey(), Collections.emptySet())
                    .stream().map(item -> new AbstractMap.SimpleEntry<>(e, item)))
            .filter(e -> itemDetailInformation.get(e.getValue()).getPrefAs().stream()
                    .anyMatch(e.getKey().getValue().getSupportedPrefAs()::contains))
            .collect(Collectors.groupingBy(e -> e.getKey().getKey(), Collectors.mapping(Map.Entry::getValue, Collectors.toSet())));
}

但是我认为这不会使您的代码更具可读性。希望这会有所帮助。