Java实现文本文件停用词过滤与词频统计教程

云辰小哥_5157

云辰小哥_5157

2025-08-26

850人浏览

原创

Java实现文本文件停用词过滤与词频统计教程

本教程详细讲解如何使用Java高效处理文本文件,实现停用词的过滤和剩余词汇的频率统计。我们将利用NIO.2的Files类进行文件读写,结合字符串操作移除指定停用词,并通过HashMap统计词频,最终展示如何获取并排序高频词汇。

在文本处理任务中,停用词过滤(stop word removal)和词频统计(word frequency counting)是两个非常常见的步骤。停用词通常是那些在文本中出现频率很高但对文本含义贡献不小的词,例如“的”、“是”、“在”等。通过过滤这些词,我们可以更有效地分析文本的核心内容。本教程将指导您如何使用java实现这一过程。

1. 文件读取与停用词加载

处理文本文件的第一步是将其内容读取到内存中。Java NIO.2 提供的 java.nio.file.Files 类使得文件读写变得非常简洁高效。我们将使用 Files.readString() 方法来读取整个文件的内容。

首先,假设我们有两个文件:

  • hello.txt: 包含待处理的原始文本。
  • stopwords.txt: 包含需要过滤的停用词,每行一个或以空格分隔。
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class TextProcessor {

    public static void main(String[] args) {
        // 创建示例文件 (实际应用中这些文件应已存在)
        createExampleFiles(); 

        try {
            // 1. 读取原始文本文件
            String helloTxtContent = Files.readString(Paths.get("hello.txt"), Charset.defaultCharset());
            System.out.println("原始文本内容:
" + helloTxtContent);

            // 2. 读取停用词文件
            String stopWordsTxtContent = Files.readString(Paths.get("stopwords.txt"), Charset.defaultCharset());
            // 将停用词解析为一个Set,方便快速查找
            Set<string> stopWords = Arrays.stream(stopWordsTxtContent.split("\s+"))
                                          .map(String::toLowerCase) // 转换为小写以实现不区分大小写的匹配
                                          .collect(Collectors.toSet());
            System.out.println("
停用词列表:
" + stopWords);

            // ... 后续处理 ...

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 辅助方法:创建示例文件
    private static void createExampleFiles() {
        try {
            Files.writeString(Paths.get("hello.txt"), "remove leave remove leave remove leave re move remov e leave remove hello remove world!");
            Files.writeString(Paths.get("stopwords.txt"), "remove world");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}</string>

在上述代码中,我们首先通过 Files.readString() 读取了两个文件的内容。对于停用词,我们将其内容按空格分割,并转换为小写后存储在一个 Set 中,这有助于后续进行高效的包含性检查。

2. 高效停用词过滤

读取文件内容后,下一步是移除文本中的停用词。Java的 String.replaceAll() 方法结合正则表达式是实现这一功能的强大工具。为了确保只替换完整的单词而不是单词的一部分,我们需要使用正则表达式的单词边界 。

// ... (接上一段代码)

            // 3. 过滤停用词
            String filteredText = helloTxtContent;
            for (String stopWord : stopWords) {
                // 使用正则表达式  确保只匹配完整的单词
                // 忽略大小写匹配,并替换为空字符串
                filteredText = filteredText.replaceAll("(?i)\b" + stopWord + "\b", "");
            }
            // 移除可能因为替换而产生的多余空格
            filteredText = filteredText.replaceAll("\s+", " ").trim();
            System.out.println("
过滤停用词后的文本:
" + filteredText);

            // ... 后续处理 ...

这里,"(?i)\b" + stopWord + "\b" 是一个关键的正则表达式:

  • (?i):表示不区分大小写匹配。
  • :匹配单词边界。例如,remove 只会匹配独立的 "remove",而不会匹配 "remover" 中的 "remove"。
  • replaceAll():将所有匹配到的停用词替换为空字符串。
  • 最后,replaceAll("\s+", " ").trim() 用于清理因删除单词可能产生的多个连续空格,并去除首尾空格。

3. 将处理结果写回文件

如果需要将过滤后的文本保存到文件中,可以使用 Files.writeString() 方法。

Java Api Extractor
Java Api Extractor

从 Java 项目中提取 Controller 层接口定义为 JSON 数据。

下载
// ... (接上一段代码)

            // 4. 将过滤后的文本写回文件 (可选)
            String outputFilePath = "filtered_hello.txt";
            Files.writeString(Paths.get(outputFilePath), filteredText, Charset.defaultCharset());
            System.out.println("
过滤后的文本已保存到: " + outputFilePath);

            // ... 后续处理 ...

这会将 filteredText 的内容写入到名为 filtered_hello.txt 的新文件中。如果文件已存在,其内容将被覆盖。

4. 词频统计与排序

过滤完停用词后,我们可以对剩余的文本进行词频统计。这通常涉及以下步骤:

  1. 分词 (Tokenization):将文本分割成单个单词。
  2. 标准化 (Normalization):将单词转换为小写,并移除标点符号,以确保 "Hello" 和 "hello" 被视为同一个词。
  3. 计数 (Counting):使用 HashMap 存储每个单词及其出现次数。
  4. 排序 (Sorting):根据词频对单词进行排序,找出高频词。
// ... (接上一段代码)

            // 5. 词频统计
            Map<string integer> wordFrequencies = new HashMap();
            // 将文本分割成单词,并进行标准化处理
            // 使用正则表达式匹配非字母数字字符,将其替换为空格,然后按空格分割
            String[] words = filteredText.toLowerCase().split("[^a-zA-Z0-9]+"); 

            for (String word : words) {
                if (!word.isEmpty()) { // 排除空字符串
                    wordFrequencies.put(word, wordFrequencies.getOrDefault(word, 0) + 1);
                }
            }

            System.out.println("
原始词频统计:
" + wordFrequencies);

            // 6. 排序并获取Top N词汇
            int topN = 5; // 例如,获取前5个高频词
            List<map.entry integer>> sortedFrequencies = wordFrequencies.entrySet()
                    .stream()
                    .sorted(Map.Entry.<string integer>comparingByValue().reversed()) // 按词频降序排列
                    .limit(topN) // 取前N个
                    .collect(Collectors.toList());

            System.out.println("
Top " + topN + " 高频词汇:");
            for (Map.Entry<string integer> entry : sortedFrequencies) {
                System.out.println("  " + entry.getKey() + ": " + entry.getValue());
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 辅助方法:创建示例文件 (已在前面定义,这里不再重复)
    // private static void createExampleFiles() { ... }
}</string></string></map.entry></string>

在词频统计部分:

  • filteredText.toLowerCase().split("[^a-zA-Z0-9]+"):将过滤后的文本转换为小写,然后使用正则表达式 [^a-zA-Z0-9]+ (匹配一个或多个非字母数字字符) 来分割文本,有效地将标点符号作为分隔符。
  • wordFrequencies.getOrDefault(word, 0) + 1:这是统计词频的常用模式,如果单词已存在,则计数加一;否则,初始化为1。
  • 使用Java Stream API进行排序:comparingByValue().reversed() 实现按词频降序排列,limit(topN) 限制结果数量。

5. 完整示例代码

将上述所有部分整合,形成一个完整的文本处理工具类:

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class TextProcessor {

    public static void main(String[] args) {
        // 辅助方法:创建示例文件 (实际应用中这些文件应已存在)
        createExampleFiles(); 

        try {
            // 1. 读取原始文本文件
            String helloTxtContent = Files.readString(Paths.get("hello.txt"), Charset.defaultCharset());
            System.out.println("原始文本内容:
" + helloTxtContent);

            // 2. 读取停用词文件并解析为Set
            String stopWordsTxtContent = Files.readString(Paths.get("stopwords.txt"), Charset.defaultCharset());
            Set<string> stopWords = Arrays.stream(stopWordsTxtContent.split("\s+"))
                                          .map(String::toLowerCase)
                                          .collect(Collectors.toSet());
            System.out.println("
停用词列表:
" + stopWords);

            // 3. 过滤停用词
            String filteredText = helloTxtContent;
            for (String stopWord : stopWords) {
                filteredText = filteredText.replaceAll("(?i)\b" + stopWord + "\b", "");
            }
            filteredText = filteredText.replaceAll("\s+", " ").trim(); // 清理多余空格
            System.out.println("
过滤停用词后的文本:
" + filteredText);

            // 4. 将过滤后的文本写回文件 (可选)
            String outputFilePath = "filtered_hello.txt";
            Files.writeString(Paths.get(outputFilePath), filteredText, Charset.defaultCharset());
            System.out.println("
过滤后的文本已保存到: " + outputFilePath);

            // 5. 词频统计
            Map<string integer> wordFrequencies = new HashMap();
            String[] words = filteredText.toLowerCase().split("[^a-zA-Z0-9]+"); 

            for (String word : words) {
                if (!word.isEmpty()) {
                    wordFrequencies.put(word, wordFrequencies.getOrDefault(word, 0) + 1);
                }
            }

            System.out.println("
原始词频统计:
" + wordFrequencies);

            // 6. 排序并获取Top N词汇
            int topN = 5; 
            List<map.entry integer>> sortedFrequencies = wordFrequencies.entrySet()
                    .stream()
                    .sorted(Map.Entry.<string integer>comparingByValue().reversed())
                    .limit(topN)
                    .collect(Collectors.toList());

            System.out.println("
Top " + topN + " 高频词汇:");
            for (Map.Entry<string integer> entry : sortedFrequencies) {
                System.out.println("  " + entry.getKey() + ": " + entry.getValue());
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 辅助方法:创建示例文件
    private static void createExampleFiles() {
        try {
            Files.writeString(Paths.get("hello.txt"), "remove leave remove leave remove leave re move remov e leave remove hello remove world!");
            Files.writeString(Paths.get("stopwords.txt"), "remove world");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}</string></string></map.entry></string></string>

6. 注意事项

  • 文件编码: 在 Files.readString() 和 Files.writeString() 中指定 Charset.defaultCharset() 是一个方便的选择,但更好的实践是明确指定文件编码(例如 StandardCharsets.UTF_8),以避免跨平台或特定环境下的乱码问题。
  • 正则表达式精度:  单词边界在大多数情况下工作良好,但对于某些特殊语言或复杂文本结构,可能需要更精细的正则表达式来定义“单词”。
  • 性能考虑: 对于非常大的文件(GB级别),Files.readString() 会一次性将整个文件读入内存,这可能导致内存溢出。对于这类场景,应考虑使用 Files.lines() 结合 Stream 或 BufferedReader 逐行处理文件,以减少内存占用。
  • 标点符号处理: 词频统计时,split("[^a-zA-Z0-9]+") 会将所有非字母数字字符视为分隔符。如果需要保留某些标点符号(例如连字符),则需要调整正则表达式。
  • 大小写敏感性: 停用词过滤和词频统计都建议转换为小写进行处理,以确保“The”和“the”被视为同一个词。

总结

通过本教程,我们学习了如何使用Java NIO.2的 Files 类进行高效的文件读写,利用 String.replaceAll() 结合正则表达式实现精确的停用词过滤,并通过 HashMap 和 Stream API 完成词频统计与排序。掌握这些技术,您将能够有效地处理各种文本数据,为更高级的文本分析任务打下坚实的基础。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

2023.06.20

4696

8

正则表达式不包含
正则表达式不包含

正则表达式,又称规则表达式,,是一种文本模式,包括普通字符和特殊字符,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式的文本。php中文网给大家带来了有关正则表达式的相关教程以及文章,希望对大家能有所帮助。

2023.07.05

3181

4

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

8842

9

java正则表达式匹配字符串
java正则表达式匹配字符串

在Java中,我们可以使用正则表达式来匹配字符串。本专题为大家带来java正则表达式匹配字符串的相关内容,帮助大家解决问题。

2023.08.11

812

5

正则表达式空格
正则表达式空格

正则表达式空格可以用“\s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。本专题为大家提供正则表达式相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.31

520

5

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.13

693

12

正则表达式空格如何表示
正则表达式空格如何表示

正则表达式空格可以用“\s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。想了解更多正则表达式空格怎么表示的内容,可以访问下面的文章。

2023.11.17

406

3

正则表达式中如何匹配数字
正则表达式中如何匹配数字

正则表达式中可以通过匹配单个数字、匹配多个数字、匹配固定长度的数字、匹配整数和小数、匹配负数和匹配科学计数法表示的数字的方法匹配数字。更多关于正则表达式的相关知识详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.12.06

739

7

php正则表达式有哪些
php正则表达式有哪些

php正则表达式有"/pattern/"、"^"、"$"、"."、"[]"、"[^]"、"[a-z]"、"[A-Z]"、"[0-9]"、"\d"、"\D"、"\w"、"\W"、&a

2024.02.23

312

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习