【发布时间】:2016-03-11 03:57:43
【问题描述】:
我在 Richard Bird 的书中读到了这个问题:在War and Peace(或任何其他文本)中找到最常用的五个词。
这是我目前的尝试:
public class WarAndPeace {
public static void main(String[] args) throws Exception {
Map<String, Integer> wc =
Files.lines(Paths.get("/tmp", "/war-and-peace.txt"))
.map(line -> line.replaceAll("\\p{Punct}", ""))
.flatMap(line -> Arrays.stream(line.split("\\s+")))
.filter(word -> word.matches("\\w+"))
.map(s -> s.toLowerCase())
.filter(s -> s.length() >= 2)
.collect(Collectors.toConcurrentMap(
w -> w, w -> 1, Integer::sum));
wc.entrySet()
.stream()
.sorted((e1, e2) -> Integer.compare(e2.getValue(), e1.getValue()))
.limit(5)
.forEach(e -> System.out.println(e.getKey() + ": " + e.getValue()));
}
}
这绝对看起来很有趣并且运行速度相当快。在我的笔记本电脑上打印以下内容:
$> time java -server -Xmx10g -cp target/classes tmp.WarAndPeace
the: 34566
and: 22152
to: 16716
of: 14987
a: 10521
java -server -Xmx10g -cp target/classes tmp.WarAndPeace 1.86s user 0.13s system 274% cpu 0.724 total
它通常在 2 秒内运行。您能否从表现力和性能的角度提出进一步的改进建议?
PS:如果您对这个问题的丰富历史感兴趣,请参阅here。
【问题讨论】:
-
有趣的问题,虽然可能比 Stack Overflow 更适合代码审查
-
我建议你在 Code Review 上问这个问题:codereview.stackexchange.com
-
类似代码,stackoverflow.com/a/33323127/2855515。检查 splitAsStream。大声笑,或者只是阅读 tagir 的答案。
标签: java-8 java-stream