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

时间:2019-12-15 21:14:16

标签: java java-8 guava

我有一个字符串列表,其中每个字符串由字母组成,这些字母由字符“,”(逗号)分隔。 我想遍历字符串列表,以逗号分隔,计算每个字母出现多少次,并将结果存储在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]
}

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

这是实际情况中的简化示例,但仍然可以捕捉到我的问题的本质

1 个答案:

答案 0 :(得分:5)

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

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