首页 > 解决方案 > 如何通过流计算地图中的单词

问题描述

我正在使用List<String>- 它包含一个大文本。文字看起来像:

List<String> lines = Arrays.asList("The first line", "The second line", "Some words can repeat", "The first the second"); //etc

我需要用输出计算其中的单词:

first - 2
line - 2
second - 2
can - 1
repeat - 1
some - 1
words - 1

应该跳过短于 4 个符号的单词,这就是为什么“the”和“can”不在输出中的原因。这里我写了这个例子,但是如果这个词很稀有并且entry < 20,我应该跳过这个词。然后按字母顺序对地图进行排序。仅使用流,不使用“if”、“while”和“for”结构。

我已经实施的:

Map<String, Integer> wordCount = Stream.of(list)
                .flatMap(Collection::stream)
                .flatMap(str -> Arrays.stream(str.split("\\p{Punct}| |[0-9]|…|«|»|“|„&quot;)))
                .filter(str -> (str.length() >= 4))
                .collect(Collectors.toMap(
                        i -> i.toLowerCase(),
                        i -> 1,
                        (a, b) -> java.lang.Integer.sum(a, b))
                );

wordCount 包含带有单词及其条目的 Map。但是我怎么能跳过生僻词呢?我应该创建新的流吗?如果是,我怎样才能获得地图的价值?我试过这个,但它不正确:

 String result = Stream.of(wordCount)
         .filter(i -> (Map.Entry::getValue > 10));

我的计算应该返回一个字符串:

"word" - number of entries

谢谢!

标签: javadictionarylambdacollectionsjava-stream

解决方案


rare在计算频率计数之前,您不能排除任何小于的值。

这是我可能会做的事情。

  • 做频率计数(我选择做的方式与你略有不同)。
  • 然后流式传输地图的 entrySet 并过滤掉小于某个频率的值。
  • 然后使用 a 重构地图以TreeMap按词汇顺序对单词进行排序
List<String> list = Arrays.asList(....);

int wordRarity = 10; // minimum frequency to accept
int wordLength = 4; // minimum word length to accept
        
Map<String, Long> map = list.stream()
        .flatMap(str -> Arrays.stream(
                str.split("\\p{Punct}|\\s+|[0-9]|…|«|»|“|„&quot;)))
        .filter(str -> str.length() >= wordLength)
        .collect(Collectors.groupingBy(String::toLowerCase, 
                Collectors.counting()))
        // here is where the rare words are filtered out.
        .entrySet().stream().filter(e->e.getValue() > wordRarity)
        .collect(Collectors.toMap(Entry::getKey, Entry::getValue,
                (a,b)->a,TreeMap::new));
    }

请注意,(a,b)->alambda 是处理重复项的合并函数,未使用。不幸的是,如果不指定合并功能,就无法指定供应商。

打印它们的最简单方法如下:

map.entrySet().forEach(e -> System.out.printf("%s - %s%n",
                e.getKey(), e.getValue()));

推荐阅读