当前位置:   article > 正文

统计一篇超过10G的文章中每个单词出现的次数_一台电脑读取10g的文本并统计top10的单词

一台电脑读取10g的文本并统计top10的单词

目录

一、思路总结

二、代码展示

三、继续探讨

(一)统计一篇超过10G的文章中每个单词出现的次数对应的相关技术思考

(二)关联继续思考


一、思路总结

统计一篇超过10G的文章中每个单词出现的次数,可以通过分布式计算来提高效率。以下是一种可能的实现方式:

  1. 首先,将文本切分成多个小文件,每个小文件大小适中,比如 100MB。将这些小文件分别分配到多台计算机上进行处理。
  2. 在每台计算机上,使用多线程读取小文件中的内容,将单词拆分出来,并将每个单词作为 key,对应的出现次数作为 value 存储到本地内存中的一个 hash map 中。
  3. 当一个小文件被处理完成后,将这个 hash map 中的所有单词出现次数合并到一个全局的 hash map 中。这个全局的 hash map 可以存储在一个共享的存储系统中,比如 Redis。
  4. 所有小文件处理完成后,最终得到的全局 hash map 就是每个单词在整个文章中出现的次数了。

这种实现方式的优点是可以利用多台计算机和多线程来并行处理数据,从而提高处理速度。同时,每个计算机只需要在本地存储一部分数据,可以有效减少单个计算机的内存占用。 

另外,如果要进一步优化性能,可以考虑使用 Bloom Filter 等数据结构来减少单词哈希冲突的概率,从而提高准确性。同时,可以通过数据预处理和缓存等方式来减少单词拆分和哈希计算的时间,提高计算效率。

二、代码展示

按照以上思路,我展示下处理文本数据统计的代码,具体展示如下:

  1. package org.zyf.javabasic.letcode;
  2. import com.google.common.hash.BloomFilter;
  3. import com.google.common.hash.Funnels;
  4. import java.io.BufferedReader;
  5. import java.io.FileReader;
  6. import java.io.IOException;
  7. import java.nio.charset.Charset;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10. import java.util.concurrent.ExecutorService;
  11. import java.util.concurrent.Executors;
  12. import java.util.concurrent.TimeUnit;
  13. import java.util.regex.Pattern;
  14. /**
  15. * @author yanfengzhang
  16. * @description 统计一篇超过10G的文章中每个单词出现的次数
  17. * @date 2023/4/9 12:24
  18. */
  19. public class WordCount {
  20. /*线程数*/
  21. private static final int NUM_THREADS = 4;
  22. /*单词的正则表达式*/
  23. private static final Pattern WORD_PATTERN = Pattern.compile("[^a-zA-Z0-9]");
  24. public static void main(String[] args) throws IOException, InterruptedException {
  25. long startTime = System.currentTimeMillis();
  26. String filePath = "/Users/yanfengzhang/Downloads/zyfTestData.txt";
  27. /*读取文件并分割成多个子任务*/
  28. Map<String, Integer> wordCounts = new HashMap<>();
  29. BloomFilter<CharSequence> bloomFilter = BloomFilter.create(
  30. Funnels.stringFunnel(Charset.forName("UTF-8")),
  31. 1000000000,
  32. 0.01);
  33. try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
  34. String line;
  35. while ((line = br.readLine()) != null) {
  36. String[] words = WORD_PATTERN.split(line);
  37. for (String word : words) {
  38. if (!word.isEmpty()) {
  39. String lowerCaseWord = word.toLowerCase();
  40. if (!bloomFilter.mightContain(lowerCaseWord)) {
  41. bloomFilter.put(lowerCaseWord);
  42. wordCounts.put(lowerCaseWord, wordCounts.getOrDefault(lowerCaseWord, 0) + 1);
  43. }
  44. }
  45. }
  46. }
  47. }
  48. /*按照线程数分割成多个任务并发执行*/
  49. ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
  50. int numWordsPerThread = wordCounts.size() / NUM_THREADS;
  51. int startIndex = 0;
  52. for (int i = 0; i < NUM_THREADS; i++) {
  53. int endIndex = (i == NUM_THREADS - 1) ? wordCounts.size() : (startIndex + numWordsPerThread);
  54. executor.submit(new WordCounter(wordCounts, bloomFilter, startIndex, endIndex));
  55. startIndex = endIndex;
  56. }
  57. executor.shutdown();
  58. executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
  59. long endTime = System.currentTimeMillis();
  60. /*输出结果*/
  61. wordCounts.entrySet().stream()
  62. .sorted(Map.Entry.comparingByValue((a, b) -> b - a))
  63. .limit(100)
  64. .forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue()));
  65. System.out.println("Elapsed time: " + (endTime - startTime) / 1000.0 + "s");
  66. }
  67. /**
  68. * 子任务:统计指定区间的单词出现次数
  69. */
  70. private static class WordCounter implements Runnable {
  71. private final Map<String, Integer> wordCounts;
  72. private final BloomFilter<CharSequence> bloomFilter;
  73. private final int startIndex;
  74. private final int endIndex;
  75. public WordCounter(Map<String, Integer> wordCounts, BloomFilter<CharSequence> bloomFilter, int startIndex, int endIndex) {
  76. this.wordCounts = wordCounts;
  77. this.bloomFilter = bloomFilter;
  78. this.startIndex = startIndex;
  79. this.endIndex = endIndex;
  80. }
  81. @Override
  82. public void run() {
  83. int i = 0;
  84. for (Map.Entry<String, Integer> entry : wordCounts.entrySet()) {
  85. if (i >= startIndex && i < endIndex) {
  86. String word = entry.getKey();
  87. if (!bloomFilter.mightContain(word)) {
  88. /*如果布隆过滤器中不存在该单词,则跳过*/
  89. continue;
  90. }
  91. int count = entry.getValue();
  92. wordCounts.put(word, count);
  93. }
  94. i++;
  95. }
  96. }
  97. }
  98. }

三、继续探讨

(一)统计一篇超过10G的文章中每个单词出现的次数对应的相关技术思考

  1. 数据的处理方式:对于10G这样的大数据,通常无法一次性加载到内存中进行处理。因此,我们需要考虑如何对数据进行分块、分批次加载、并发处理等方面的优化,以提高处理效率和准确性。
  2. 哈希算法的选择:哈希算法是单词计数的关键,它决定了单词计数的准确性和效率。对于大数据,哈希算法的性能和冲突率都是需要考虑的因素。我们可以使用一些优秀的哈希算法,如MurmurHash、CityHash等,以及优秀的哈希算法库,如Google的FarmHash、SpookyHash等。
  3. 并行计算的优化:在多核CPU和分布式计算环境下,我们可以考虑并行计算的优化,以充分利用计算资源提高计算效率。例如可以使用并发编程框架,如Java的Fork/Join框架、Hadoop、Spark等,并结合分布式文件系统、分布式数据库等技术,提高处理速度。
  4. 算法的优化:除了哈希算法外,我们还可以考虑其他算法的优化。例如可以使用Trie树、倒排索引等数据结构,提高单词查找的速度和准确性。
  5. 系统资源的管理:在处理大数据时,系统资源的管理也是非常重要的一环。例如可以优化JVM的内存管理、设置GC策略、合理利用操作系统的缓存等,以提高系统的稳定性和处理效率。

(二)关联继续思考

统计一篇超过10G的文章中每个单词出现的次数需要处理大量的文本数据,这里有一些可以探讨的相关问题:

  1. 处理大规模文本数据的数据结构和算法:对于大量文本数据的处理,需要选择适当的数据结构和算法来优化性能。例如,可以使用 Bloom Filter 来减少单词哈希冲突的概率,使用多线程处理数据以提高处理速度。
  2. 存储和处理大规模文本数据的工具和技术:处理超过10G的文本数据需要使用到大规模数据存储和处理的工具和技术。例如,可以使用 Hadoop、Spark 等分布式计算框架来处理大规模数据,使用 Redis、HBase 等分布式存储系统来存储数据。
  3. 处理文本数据的语言处理技术:在文本数据处理中,可以应用一些自然语言处理技术来处理文本数据。例如,可以使用分词、词性标注等技术来处理单词,并使用词向量、主题模型等技术来分析文本数据。
  4. 数据质量和准确性:在处理大规模文本数据时,需要考虑数据质量和准确性的问题。例如,需要处理缺失数据、重复数据、错误数据等问题。可以使用数据清洗和预处理技术来提高数据质量和准确性。

综上,处理大规模文本数据是一个综合性问题,需要综合运用数据结构和算法、工具和技术、自然语言处理技术以及数据质量和准确性的问题来解决。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/615476
推荐阅读
相关标签
  

闽ICP备14008679号