采集流时如何使用Guava的Multisets.toMultiSet()?

How to use Guava's Multisets.toMultiSet() when collecting a stream?

我有一个字符串列表,其中每个字符串由字符“,”(逗号)分隔的字母组成。 我想遍历字符串列表,以逗号分隔,计算每个字母出现的次数,并将结果存储在 Multiset 中。应忽略空白字符串,并应修剪拆分部分。多集应该按键排序。

下面的代码有效,即它产生了所需的多重集。但是,我无法弄清楚如何使用正确的收集器方法 (Multisets.toMultiset()),因此采用了两步解决方案,使用了一个我想消除的临时列表变量。

如果有人能告诉我应该如何在收集步骤中构建对 Multisets.toMultiset() 的调用,我将不胜感激。我被困在定义元素函数和供应商函数上,我什至无法编写编译的代码...

@Test
public void testIt() {
    List<String> temp = Stream.of("b, c", "a", "  ", "a, c")
            .filter(StringUtils::isNotBlank)
            .map(val -> val.split(","))
            .flatMap(Arrays::stream)
            .map(String::trim)
            .collect(Collectors.toList());

    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(temp);

    System.out.println("As list: " + temp);
    System.out.println("As multiset: " + multiset);
    // Output is:
    // As list: [b, c, a, a, c]
    // As multiset: [a x 2, b, c x 2]
}

我正在使用 Guava 28.1。上例中还使用了 commons-lang3 版本 3.9

中的 StringUtils class

这是真实场景中的一个简化示例,但仍然抓住了我的问题的本质

如果你真的想省略第二个复制阶段,有几种方法可以实现:

  1. 已经指定了一个 ImmatbleSortedMultiset 收集器

    .collect(ImmutableSortedMultiset.toImmutableSortedMultiset(Comparator.naturalOrder()));
    
  2. 因为你问的是如何使用 MultiSets::toMultiset

    .collect(Multisets.toMultiset(Function.identity(), i -> 1, TreeMultiset::create));
    
  3. 或者您可以使用 Builder

    完美添加您自己的 Collector 实现
    .collect(Collector.of(
        ImmutableSortedMultiset::<String>naturalOrder,
        ImmutableSortedMultiset.Builder::add,
        (b1, b2) -> {b1.addAll(b2.build()); return b1;},
        ImmutableSortedMultiset.Builder::build)
    );