0

0

Java实现:高效查找字符串列表中最常见的N-gram短语

心靈之曲

心靈之曲

发布时间:2025-11-18 14:53:10

|

786人浏览过

|

来源于php中文网

原创

Java实现:高效查找字符串列表中最常见的N-gram短语

本教程详细介绍了如何在java中从一系列预处理过的句子中,高效地识别并提取最常见的连续词对(n-gram,此处特指bigram)。文章通过迭代处理单词列表,构建n-gram短语,并利用hashmap进行频率统计,最终找出出现次数最多的短语,为文本分析和自然语言处理任务提供实用方法。

1. 引言:N-gram及其在文本分析中的作用

在自然语言处理(NLP)领域,N-gram是一种重要的文本分析技术,它指的是文本中连续出现的N个词语序列。例如,当N=1时,我们称之为Unigram(即单个词);当N=2时,称之为Bigram(词对);当N=3时,称之为Trigram(词三元组)。通过分析N-gram的频率,我们可以揭示文本中的常见短语、语言模式,这对于关键词提取、主题建模、机器翻译和语音识别等任务都至关重要。

本文将着重讲解如何在Java环境中,基于已有的单词列表(通常是经过预处理,如分词、去除停用词和标点符号后的结果),扩展单词频率统计方法,实现对最常见Bigram(连续词对)的查找。

2. 核心思路:利用HashMap统计N-gram频率

立即学习Java免费学习笔记(深入)”;

给定一个表示句子集合的数据结构 ArrayList<ArrayList<String>> sentences,其中每个内部 ArrayList<String> 代表一个句子中已处理的单词序列。要找到最常见的连续词对,我们需要采取以下步骤:

闪念贝壳
闪念贝壳

闪念贝壳是一款AI 驱动的智能语音笔记,随时随地用语音记录你的每一个想法。

下载
  1. 遍历句子集合: 依次处理每一个句子。
  2. 生成N-gram: 对于每个句子中的单词序列,从头到尾遍历,每次取出相邻的N个词(对于Bigram,即两个词)组合成一个N-gram短语。
  3. 频率统计: 使用一个 HashMap<String, Integer> 来存储生成的N-gram短语及其出现的次数。N-gram短语作为Map的键(Key),出现次数作为值(Value)。
  4. 查找最常见N-gram: 在所有N-gram及其频率统计完毕后,遍历这个HashMap,找出具有最大出现次数的N-gram短语。

3. Java实现:查找最常见的Bigram

以下Java代码展示了如何实现上述思路,以查找最常见的Bigram:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map; // 导入Map接口以便遍历

public class NGramAnalyzer {

    /**
     * 查找给定句子列表中最常见的Bigram(连续词对)。
     *
     * @param sentences 一个ArrayList的ArrayList,其中每个内部ArrayList代表一个句子的单词序列。
     * @return 最常见的Bigram字符串。如果输入为空或没有Bigram,则返回空字符串。
     */
    public static String getMostCommonNGram(ArrayList<ArrayList<String>> sentences) {
        // 用于存储Bigram及其出现次数的HashMap
        HashMap<String, Integer> nGramMap = new HashMap<>();

        // 1. 遍历句子集合
        for (ArrayList<String> words : sentences) {
            // 2. 生成Bigram并统计频率
            // 循环到 words.size() - 1 是为了确保 i + 1 不会越界
            for (int i = 0; i < words.size() - 1; i++) {
                // 构建Bigram,例如 "word1 word2"
                String nGram = words.get(i) + " " + words.get(i + 1);

                // 检查HashMap中是否已存在该Bigram,并更新计数
                // 使用getOrDefault方法可以简化代码,如果键不存在则返回默认值0
                nGramMap.put(nGram, nGramMap.getOrDefault(nGram, 0) + 1);
            }
        }

        // 3. 查找出现次数最多的Bigram
        String mostCommonNGram = "";
        int maxCount = 0;

        // 遍历HashMap的entrySet以同时获取键和值,效率更高
        for (Map.Entry<String, Integer> entry : nGramMap.entrySet()) {
            String nGram = entry.getKey();
            int count = entry.getValue();

            if (count > maxCount) {
                maxCount = count;
                mostCommonNGram = nGram;
            }
        }
        return mostCommonNGram;
    }

    // 示例用法
    public static void main(String[] args) {
        ArrayList<ArrayList<String>> sampleSentences = new ArrayList<>();

        // 模拟预处理后的句子列表
        ArrayList<String> sentence1 = new ArrayList<>();
        sentence1.add("this");
        sentence1.add("is");
        sentence1.add("a");
        sentence1.add("sample");
        sentence1.add("sentence");
        sampleSentences.add(sentence1);

        ArrayList<String> sentence2 = new ArrayList<>();
        sentence2.add("another");
        sentence2.add("sample");
        sentence2.add("sentence");
        sentence2.add("for");
        sentence2.add("analysis");
        sampleSentences.add(sentence2);

        ArrayList<String> sentence3 = new ArrayList<>();
        sentence3.add("this");
        sentence3.add("is");
        sentence3.add("a");
        sentence3.add("test");
        sampleSentences.add(sentence3);

        String commonNGram = getMostCommonNGram(sampleSentences);
        System.out.println("最常见的Bigram是: \"" + commonNGram + "\""); // 预期输出: "sample sentence"
    }
}

代码解析:

  • getMostCommonNGram(ArrayList<ArrayList<String>> sentences) 方法:
    • HashMap<String, Integer> nGramMap: 初始化一个哈希映射,用于存储每个Bigram字符串(键)及其对应的出现频率(值)。
    • 外层循环 (for (ArrayList<String> words : sentences)): 遍历输入的 sentences 列表,每次取出一个句子的单词列表 words。
    • 内层循环 (for (int i = 0; i < words.size() - 1; i++)): 遍历当前句子的单词列表 words。关键在于循环条件 i < words.size() - 1,这确保了在构建Bigram words.get(i) + " " + words.get(i + 1) 时,i + 1 不会超出列表的有效索引范围,避免 IndexOutOfBoundsException。
    • Bigram构建: String nGram = words.get(i) + " " + words.get(i + 1); 将当前词和下一个词拼接成一个Bigram字符串,中间用空格分隔,作为哈希映射的键。
    • 频率统计 (nGramMap.put(nGram, nGramMap.getOrDefault(nGram, 0) + 1);):
      • getOrDefault(key, defaultValue) 方法是Java 8引入的便捷方法。它会尝试获取 key 对应的值;如果 key 不存在于Map中,则返回 defaultValue(这里是 0)。
      • 这行代码简洁地实现了:如果Bigram首次出现,则将其计为1;如果已存在,则将其计数加1。
    • 查找最大计数 (for (Map.Entry<String, Integer> entry : nGramMap.entrySet())):
      • 在所有Bigram及其频率都统计完毕后,我们遍历 nGramMap 的 entrySet()。entrySet() 提供了同时访问键和值的迭代器,比单独遍历 keySet() 再通过 get(key) 获取值更高效。
      • maxCount 变量记录当前找到的最大频率,mostCommonNGram 记录对应的Bigram。
      • 每次发现一个频率更高的Bigram,就更新 maxCount 和 mostCommonNGram。
    • 最终,方法返回 mostCommonNGram。

4. 扩展与注意事项

  • N-gram的泛化:
    • 要查找Trigram(N=3),只需修改内层循环条件为 i < words.size() - 2,并将N-gram构建为 words.get(i) + " " + words.get(i + 1) + " " + words.get(i + 2)。
    • 可以进一步抽象为一个通用方法 getMostCommonNGram(ArrayList<ArrayList<String>> sentences, int n),通过传入 n 值来动态生成N-gram。
  • 预处理的重要性:
    • 在进行N-gram分析之前,对原始文本进行适当的预处理至关重要。这通常包括:
      • 分词 (Tokenization): 将文本分割成独立的词语。
      • 大小写转换: 通常将所有词转换为小写,以避免 "The" 和 "the" 被视为不同的词。
      • 去除标点符号: 移除逗号、句号、问号等。
      • 去除停用词 (Stop Words): 移除像 "a", "an", "the", "is" 等常见但通常不携带太多语义信息的词。
    • 本教程假设输入 sentences 已经过这些预处理。
  • 性能考量:
    • HashMap 提供平均 O(1) 的插入和查找时间复杂度,因此对于大规模文本数据,这种方法是高效的。
    • 然而,如果文本包含极大量独特的N-gram,HashMap 可能会占用大量内存。
  • 处理平局:
    • 当前代码在存在多个N-gram具有相同最高频率时,只会返回第一个遇到的那个。如果需要返回所有具有最高频率的N-gram,可以将 mostCommonNGram 改为 List<String> 类型,并在 if (count > maxCount) 时清空列表并添加当前N-gram,在 else if (count == maxCount) 时直接添加当前N-gram。
  • 空输入或短句子:
    • 如果输入的 sentences 列表为空,或者所有句子都太

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1051

2023.08.02

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

847

2023.08.22

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

203

2023.11.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

761

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1570

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

651

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1228

2024.03.22

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.4万人学习

C# 教程
C# 教程

共94课时 | 11.3万人学习

Java 教程
Java 教程

共578课时 | 82.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号