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

Eri*_*lja 1 java guava java-8

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

下面的代码有效,即它生成所需的 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]
}
Run Code Online (Sandbox Code Playgroud)

我正在使用番石榴 28.1。上例中还使用了来自 commons-lang3 版本 3.9 的 StringUtils 类

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

Flo*_*own 7

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

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

    .collect(ImmutableSortedMultiset.toImmutableSortedMultiset(Comparator.naturalOrder()));
    
    Run Code Online (Sandbox Code Playgroud)
  2. 既然你问怎么做 MultiSets::toMultiset

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

    .collect(Collector.of(
        ImmutableSortedMultiset::<String>naturalOrder,
        ImmutableSortedMultiset.Builder::add,
        (b1, b2) -> {b1.addAll(b2.build()); return b1;},
        ImmutableSortedMultiset.Builder::build)
    );
    
    Run Code Online (Sandbox Code Playgroud)

  • 严格优于 2): `Collectors.toCollection(TreeMultiset::create))` (5认同)