代码之家  ›  专栏  ›  技术社区  ›  Maurice

如何使用流的collect()按字符串列表的内容分组?

  •  1
  • Maurice  · 技术社区  · 6 年前

    我有一个数据库对象,它有一个包含字符串列表的字段。我检索所有这些对象,然后使用结果列表上的flatmap和distinct stream方法获取一个新列表,该列表包含数据库对象字符串列表可以包含的所有可能的唯一值。

    接下来,我要制作一个映射,其中键是我之前制作的字符串列表的唯一值列表,映射的值是数据库对象的列表,其中字符串列表包含各自字符串mapkey的值。

    所以我想要的是按以下分组:

    if(object.stringList().contains(respectiveMapKeyFromUniqeStringCollection) put object in object values list of that respective keymap.
    

    使用GroupingBy方法是否可以实现这种情况?

    编辑:我会进一步解释

    class VegetableMaker{
    @ElementCollection  
    private List<String> vegetableList;
    
    }
    

    让我们假设一个植物表可能包含的值是:“生菜、西红柿、菠菜、紫苏、洋葱”。

        Set<String> produceNames = vegetableMakers.stream().flatMap(vegetableMaker -> vegetableMaker.getVegetableList().stream())
    

    .distinct().collect(collectors.toset());

    现在我们有了包含前面提到的所有可能值的列表。

    我们希望使用此列表中的值作为映射中的键。

    所以地图看起来像:

    Map<uniqueStringsAsKeys, List<VegetableMaker>> map
    

    列表值包含所有VegetableMaker实例,其中VegetableList包含地图的键。因此,关键洋葱的列表将包含所有蔬菜制造者实例,其列表中包含“洋葱”。

    是否有可能使用Java流的GROPGIPEBY方法来实现这样的映射?

    编辑2:

    这是我现在拥有的解决方案,它不使用GroupingBy,而是澄清更多我想要的东西。

    编辑:在代码中更改变量以匹配前面示例中使用的变量。

    Set<VegetableMaker> vegetableMakers = vegetableMakerDao.findAll();
    Set<String> uniqueVegetableList = vegetableMakers.stream().flatMap(vegetableMaker -> affiliateLink.getKeywords().stream()).distinct().collect(Collectors.toSet());
    Map<String,Set<VegetableMaker>> vegetableMakersContainingKeywordInTheirList = new HashMap<>();
    
    uniqueVegetableList.forEach(produceName ->{
        Set<VegetableMaker> vegetableMakerSet = new HashSet<>();
        vegetableMakers.forEach( vegetableMaker -> {
            if(vegetableMaker.getVegetableList().contains(produceName))
                vegetableMakerSet.add(vegetableMaker);
        });
        vegetableMakersContainingKeywordInTheirList.put(produceName, vegetableMakerSet);
    });
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   Maurice    6 年前

    如果我正确理解你:

    List<VegetableMaker> dbObjects = List.of(
                new VegetableMaker("Salad", List.of("Onion", "Cucumber")),
                new VegetableMaker("Italian Salad", List.of("Cheese")),
                new VegetableMaker("Greek Salad", List.of("Onion")));
    
        Map<String, List<VegetableMaker>> map = dbObjects.stream()
                .flatMap(x -> x.getVegetableList().stream().map(y -> new SimpleEntry<>(x, y)))
                .collect(Collectors.groupingBy(
                        Entry::getValue,
                        Collectors.mapping(Entry::getKey, Collectors.toList())));
    
        System.out.println(map); 
    

    结果是:

    {Onion=[Salad, Greek Salad], Cheese=[Italian Salad], Cucumber=[Salad]}
    

    编辑

    这与我上面发布的内容没什么不同:

    Map<String, Set<VegetableMaker>> result = vegetableMakerList.stream()
                .flatMap(x -> x.getKeywords().stream().distinct().map(y -> new SimpleEntry<>(x, y)))
                .collect(Collectors.groupingBy(
                        Entry::getValue,
                        Collectors.mapping(Entry::getKey, Collectors.toSet())));
    
        2
  •  1
  •   marsouf    6 年前
    final Set<VegetableMaker> vegetableMakers = vegetableMakerDao.findAll();
    
    final Map<String, Set<VegetableMaker>> vegetableMakersContainingKeywordInTheirList = vegetableMakers.stream()
        .map(VegetableMaker::getKeywords)
        .flatMap(Collection::stream)
        .distinct()
        .collect(Collectors.toMap(
            Function.identity(),
            vegetable -> vegetableMakers.stream()
              .filter(vegetableMaker -> vegetableMaker.getKeywords().contains(vegetable))
              .collect(Collectors.toSet())
        ));