如何使用Stream的collect()对字符串列表的内容进行分组?

时间:2018-07-26 08:39:45

标签: java java-stream

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

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

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

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

使用groupingBy方法是否可以实现这种目的?

编辑:我将进一步解释

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

}

让我们假设一个VegetableList可以包含的可能值是:“莴苣,番茄,菠菜,rubarbe,洋葱”

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

.distinct()。collect(Collectors.toSet());

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

我们要使用此列表中的值作为地图中的键。

因此,地图将如下所示:

Map<uniqueStringsAsKeys, List<VegetableMaker>> map

列表值包含其VegetableList包含映射键的所有VegetableMaker实例。因此,关键洋葱列表将包含其清单包括“洋葱”的所有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);
});

2 个答案:

答案 0 :(得分:2)

如果我对您的理解正确:

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())));

答案 1 :(得分:1)

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())
    ));