在Java中从一个大字符串中找到单词列表及其数量的最佳方法是什么?

3

我有一个单词列表,比如:

  • Spring Data
  • Java
  • C++
  • Junit

而且我有一个非常大的文本文件或字符串。

对于我的每个单词列表中的单词,我需要找出在这个大字符串中找到该单词的出现次数?

我期望的结果是:

  • Spring Data(10)
  • Java(3)
  • C++(6)
  • Junit(0)

上面只是4个元素,但在我的情况下可能会达到几千个。我可以遍历每个元素并查找该字符串的计数,但不确定是否最佳解决方案考虑性能?你们能否为我提供一些关于找到这个问题的最佳方法的建议呢?


有几种旨在提高文本搜索效率的算法。可以研究一下"Boyer-Moore"或者"Karp and Rabin"。也许这会有所帮助。 - Philipp Murry
str.split("\\s+") 然后查看 word-frequency-count-java-8 - Bohemian
你需要单词还是短语?“Spring”是一个单词,而“Spring Data”是一个短语(即一个非空单词列表,即一个或多个单词有序组合)。 - mfulton26
定义“单词”。你有单词列表吗?一个由空格分隔的字符串? - Louis Wasserman
@mfulton26,您是正确的,我可能应该将它们称为短语。基本上,我有一系列短语,并需要在大字符串中找到每个短语的计数。 - Enthu Leo
3个回答

1

如果需要匹配包含空格的字符串,我倾向于循环遍历目标字符串列表,在文本中进行适当转义的正则表达式搜索,并记录正则表达式匹配的数量。


当然,谢谢。是的,那似乎是明智的做法。 - Enthu Leo

0
您可以通过使用Java 8的Stream API,将主字符串按空格拆分并计算strings的数量,例如:
public static void main(String[] args) throws FileNotFoundException {

    String s = "a b c d e f d g e a c v d a w s";
    Map<String, Long> wordCount = Arrays.stream(s.split("\\s"))
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    System.out.println(wordCount);
}

这种方法使用了原始字符串的许多倍存储空间。对于非常大的字符串(如问题所述),这可能会成为一个问题。使用输入流方法,它使用O(1)空间,将更适合。 - Bohemian
那将是一种过早的优化。始终首先尝试简单的方法。现在计算机有很多内存。 - bhspencer
1
@EnthuLeo 那么,你打算如何区分/拆分这些单词?我猜如果一个单词包含空格,那么它就是两个单词? - Darshan Mehta
@DarshanMehta,可能我应该说成短语。基本上我有一组短语,需要找到每个短语在一个大字符串中出现的次数。 - Enthu Leo
一个外部循环并不是样板代码,它只是一种不同的风格。我认为你的代码隐含的可读性更低。例如,你需要提前知道groupingBy()的参数是什么,以及Function.identity()和Collectors.counting()的含义。此外,在调试器中逐步执行基于流的代码也是一件事情。 - bhspencer
显示剩余2条评论

0

如果您不想使用流,可以这样做:

    String s = "a b c d e f d g e a c v d a w s";
    Map<String, Long> wordCount = new HashMap<>();
    String[] words = s.split("\\s");
    for (String word : words) {
        Long count = wordCount.get(word);
        if (count == null) {
            count = 0L;
        }
        count = count + 1L;
        wordCount.put(word, count);
    }
    System.out.println(wordCount);

你忘记了增加计数。count = 0L; wordCount.put(word, count + 1); - Sky Kelsey
确实。谢谢你提醒我。 - bhspencer
如果初始计数器不存在,你需要将其设置为0,否则在第一次出现时就会直接跳到2。 - Sky Kelsey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接