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

Java 如何使用流的collect()按字符串列表的内容分组?,java,java-stream,Java,Java Stream,我有一个数据库对象,它有一个包含字符串列表的字段。我检索所有这些对象,然后在结果列表上使用flatMap和distinct stream方法来获得一个新列表,该列表包含数据库对象字符串列表可以包含的所有可能的唯一值 接下来,我想创建一个映射,其中键是我前面创建的stringlist的唯一值列表,映射的值是数据库对象的列表,其stringlist包含相应字符串mapkey的值 因此,我想要的是按以下内容分组: if(object.stringList().contains(respectiveMa

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

接下来,我想创建一个映射,其中键是我前面创建的stringlist的唯一值列表,映射的值是数据库对象的列表,其stringlist包含相应字符串mapkey的值

因此,我想要的是按以下内容分组:

if(object.stringList().contains(respectiveMapKeyFromUniqeStringCollection) put object in object values list of that respective keymap.
使用groupingBy方法是否可以进行类似的操作

编辑:我将进一步解释

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

}
classvegetablemaker{
@元素集合
私人列表蔬菜列表;
}
让我们假设蔬菜列表可能包含的值是:“莴苣、西红柿、菠菜、红莓、洋葱”

Set produceNames=vegetableMakers.stream().flatMap(vegetableMaker->vegetableMaker.getVegetableList().stream())
.distinct().collect(collector.toSet())

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

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

因此,地图将如下所示:

Map<uniqueStringsAsKeys, List<VegetableMaker>> map
地图
列表值包含所有VegetableMaker实例,其中vegetableList包含映射键。因此,关键洋葱列表将包含其列表中包含“洋葱”的所有VegetableMaker实例

是否可以使用java流的groupingBy方法实现这样的映射

编辑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);
});
Set vegetableMakers=vegetableMakerDao.findAll();
设置uniqueVegetableList=vegetableMakers.stream().flatMap(vegetableMaker->affiliateLink.getKeywords().stream()).distinct().collect(Collectors.toSet());
Map vegetableMakers containing关键字intheirlist=new HashMap();
uniqueVegetableList.forEach(产品名称->{
Set vegetableMakerSet=newhashset();
素食者。forEach(素食者->{
if(vegetableMaker.getVegetableList().contains(produceName))
vegetableMakerSet.add(vegetableMaker);
});
vegetablemakers在irlist.put中包含关键字(productname,vegetableMakerSet);
});

如果我理解正确:

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); 
编辑

这与我在上面发布的内容没有太大区别:

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())));
Map result=vegetableMakerList.stream()
.flatMap(x->x.getKeywords().stream().distinct().map(y->new SimpleEntry(x,y)))
.collect(收集器.groupingBy(
条目::getValue,
Collectors.mapping(条目::getKey,Collectors.toSet());
最终设置vegetableMakers=vegetableMakerDao.findAll();
最终映射vegetableMakers包含关键字intheirList=vegetableMakers.stream()
.map(VegetableMaker::getKeywords)
.flatMap(集合::流)
.distinct()
.collect(collector.toMap)(
Function.identity(),
蔬菜->蔬菜制造商.stream()
.filter(vegetableMaker->vegetableMaker.getKeywords().contains(蔬菜))
.collect(收集器.toSet())
));

示例输入列表和预期输出会有很大帮助。我已经进一步解释了,请查看编辑器是否应该是
x.getVegetableList().stream().distinct().map(…)
?没有一个VegetableMaker没有字符串字段,只有一个带有植物值的列表字段。我提出了一个不使用groupingBy的解决方案,但这可能会更清楚地说明我想要实现的目标。在代码中,VegetableMaker被称为AffiliateLink,作为键的蔬菜的唯一列表被称为produceNames,我现在将代码添加到我的OP中。@Aominè如果你有这个
新的VegetableMaker(“沙拉”,list.of(“洋葱”,“黄瓜”,“洋葱”)
(洋葱两次);但我假设两个相同的成分不可能存在……我编辑了代码,使变量名称现在与上一个示例中使用的名称相同请告诉我我对代码的解释是否正确:首先,你将关键字平面映射,同时将这些关键字转换为条目,其中键是affiliatelink,值是一个唯一的关键字,对吗?因此SimpleEntry由组成。然后,您根据SimpleEntry对象中存储的唯一蔬菜进行分组。然后,对于每个蔬菜键,您映射到一个带有AffiliateLink值的集合。对吗?我认为这是一个出色的解决方案,我今天学到了一些新的东西,谢谢。
{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())));
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())
    ));