统计一篇文章中单词出现的频率(java 版)

该博客介绍了一种使用Java实现的算法,通过HashMap来统计一篇文章中各单词的出现次数。程序读取名为'Test.txt'的文件,利用StringTokenizer分割单词,并存储到HashMap中。最后,通过TreeMap按字母顺序输出所有单词及其计数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        统计一篇给定的 文章中,各个单词出现的次数的算法。用HashMap 来存放出现的单词的次数,Key 是要统计的单词,Value 是单词出现的次数。
最后再按照 Key 的升序排列出来。

import java.util.*;
import java.io.*;
 
public class CountOccurrenceOfWords {
 
    public static void main(String[] args) throws Exception {
        Map hashMap = null;
        BufferedReader infile = null;
        StringTokenizer st = null;
        String filename = "Test.txt";
        String string;
        String file = null;
        //打开一篇文章,名字是 Test.txt .
        infile = new BufferedReader(new FileReader(filename));
        while ((string = infile.readLine()) != null) {
            file += string;  //都出整篇文章,存入String中。
 
        }
 
        hashMap = new HashMap();
      
         // 取出文章中的单词,"," "." "!" " " 为各个单词的分界符。
        st = new StringTokenizer(file, " ,.!");
 
        while (st.hasMoreTokens()) {
            String key = st.nextToken();
            if (hashMap.get(key) != null) {
                int value = ((Integer) hashMap.get(key)).intValue();
                value++;
                hashMap.put(key, new Integer(value));
 
            } else {
                hashMap.put(key, new Integer(1));
            }
        }
     
         //按照单词的字母次序输出。
        Map treeMap = new TreeMap(hashMap);
        Set entrySet = treeMap.entrySet();
 
        Iterator iterator = entrySet.iterator();
 
        while (iterator.hasNext()) {
 
            System.out.println(iterator.next());
        }
 
    }
 
}
 
<think>好的,我现在需要帮助用户解决如何用Java编写一个程序来统计英文文档中每个单词的出现次数并按频率排序的问题。首先,我得理清用户的需求。用户想要的是一个Java程序,处理英文文档,统计频,然后按出现次数排序。可能需要注意的地方包括如何读取文件、分割单词、处理大小写和标点符号,以及排序的方法。 首先,我需要确定程序的基本步骤。通常,这类程序可以分为几个步骤:读取文件内容,将文本分割成单词统计每个单词的出现次数,然后按频率排序,最后输出结果。 关于文件读取,Java中常用的有BufferedReader和FileReader结合使用。可能需要处理文件路径的问题,用户可能需要指定文件路径,或者在程序里写死,但最好让用户输入路径,这样更灵活。不过用户的问题中没有提到输入方式,可能需要默认一个示例路径,比如用户文档中的test.txt,或者让用户自行修改。 接下来是分割单词。英文文档中的单词通常由空格分隔,但标点符号可能会附着在单词上,比如“word,”或者“word.”,这时候需要去掉非字母字符。可以用正则表达式来匹配单词,例如使用split("[^a-zA-Z]+"),但需要注意可能存在连续的非字母字符导致空字符串的情况,需要过滤掉。或者用Pattern和Matcher来匹配单词,比如用正则表达式\b[a-zA-Z]+\b来匹配单词边界,但可能更复杂一些。不过可能更简单的是将整个文本转换为小写或大写,然后使用split方法分割非字母字符,并过滤掉空字符串。 统计频的话,可以用HashMap来存储单词和对应的计数。遍历分割后的单词数组,对于每个单词,转换为小写(或大写)以保证大小写不敏感,然后更新HashMap中的计数。 排序的话,需要将HashMap的Entry提取出来,放入List中,然后使用Collections.sort并自定义Comparator,按值(计数)降序排序。Java 8之后可以使用Stream API来简化这个过程,比如将entrySet转为流,然后sorted按值排序,收集到List中。 然后输出结果,遍历排序后的列表,打印每个单词和其出现次数。 需要考虑的边界情况包括空文件、文件不存在、单词全为标点符号等。此外,性能方面,如果文件很大,可能需要逐行读取而不是一次性读取整个文件,以避免内存不足。但用户的问题可能更关注基本实现,暂不考虑大文件处理。 现在,把这些步骤转化为Java代码。例如: 1. 读取文件内容:使用BufferedReader读取文件,逐行读取并拼接成字符串。 2. 分割单词:转换为小写,用正则表达式分割非字母字符,得到单词数组。 3. 统计频:遍历数组,更新HashMap。 4. 排序:将entry转为List,使用自定义比较器按值降序排序。 5. 输出结果。 可能的代码结构如下: import java.io.*; import java.util.*; public class WordFrequencyCounter { public static void main(String[] args) { try { BufferedReader reader = new BufferedReader(new FileReader("input.txt")); String line; StringBuilder content = new StringBuilder(); while ((line = reader.readLine()) != null) { content.append(line).append(" "); } reader.close(); String[] words = content.toString().toLowerCase().split("[^a-zA-Z]+"); Map<String, Integer> frequencyMap = new HashMap<>(); for (String word : words) { if (!word.isEmpty()) { frequencyMap.put(word, frequencyMap.getOrDefault(word, 0) + 1); } } List<Map.Entry<String, Integer>> entries = new ArrayList<>(frequencyMap.entrySet()); entries.sort((a, b) -> b.getValue().compareTo(a.getValue())); for (Map.Entry<String, Integer> entry : entries) { System.out.println(entry.getKey() + ": " + entry.getValue()); } } catch (IOException e) { e.printStackTrace(); } } } 需要注意的点: - 文件路径是否正确,需要处理IOException。 - 分割后的单词可能包含空字符串,需要过滤。 - 排序时的比较器是否正确降序排列。 - 是否处理大小写,比如将单词转为小写,这样"The"和"the"算作同一个。 - 标点符号的处理是否正确,例如用正则表达式[^a-zA-Z]+来分割非字母字符。 用户可能需要更详细的解释,比如代码的每一部分的作用,以及可能的改进点,比如使用Java 8的Stream API,或者处理更复杂的单词分割情况(如连字符等)。此外,可能需要考虑性能优化,比如大文件的处理,或者更高效的数据结构。 在相关问题部分,可以生成关于如何处理更复杂的文本分析、如何优化性能、或者如何扩展程序功能的问题。</think>要编写一个Java程序统计英文文档频并按频率排序,可以按照以下步骤实现: ### 1. 实现代码 ```java import java.io.*; import java.util.*; import java.util.stream.Collectors; public class WordCounter { public static void main(String[] args) throws IOException { // 读取文件内容 BufferedReader reader = new BufferedReader(new FileReader("document.txt")); StringBuilder content = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { content.append(line).append(" "); } reader.close(); // 分割单词并过滤空字符串 String[] words = content.toString() .toLowerCase() .split("[^a-zA-Z]+"); // 正则表达式分割非字母字符[^1] // 统计频 Map<String, Integer> frequencyMap = new HashMap<>(); for (String word : words) { if (word.length() > 0) { frequencyMap.put(word, frequencyMap.getOrDefault(word, 0) + 1); } } // 按频排序 List<Map.Entry<String, Integer>> sortedEntries = frequencyMap.entrySet() .stream() .sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue())) .collect(Collectors.toList()); // 输出结果 sortedEntries.forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue())); } } ``` ### 2. 关键步骤说明 1. **文件读取**:使用`BufferedReader`逐行读取文件,避免一次性加载大文件导致内存溢出 2. **单词分割**: - `toLowerCase()`保证大小写不敏感 - 正则表达式`[^a-zA-Z]+`过滤所有非字母字符作为分隔符 3. **统计**:通过`HashMap`的`getOrDefault`方法实现高效计数 4. **排序实现**:使用Java Stream API按频降序排序 5. **结果输出**:通过lambda表达式简洁地遍历输出 ### 3. 扩展优化建议 - 添加`try-catch`块处理文件不存在异常 - 使用`Paths`类支持多文件格式(如PDF、DOCX)解析 - 对超大规模文件采用分块读取处理 - 添加停用过滤功能(如忽略"the","and"等常见
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值