在Java中开发简易搜索引擎模型,核心是通过字符串匹配技术实现关键词检索功能,整体逻辑会包含文本预处理、索引构建、匹配查询三个核心环节,我们可以基于基础字符串匹配算法逐步搭建完整功能。

核心需求与功能规划
简易搜索引擎模型不需要处理海量数据,核心实现以下基础功能即可:
- 支持导入多个本地文本文件作为检索数据源
- 对数据源内容进行分词预处理,构建简单倒排索引
- 接收用户输入的搜索关键词,返回匹配的文件列表及匹配次数
- 支持简单的关键词高亮展示
核心字符串匹配算法选择
字符串匹配是搜索引擎的核心,针对简易模型我们可以选择两种常用算法:
1. 朴素匹配算法
实现逻辑简单,适合数据量小的场景,核心是逐个比对字符,匹配成功则返回位置。算法时间复杂度为O(n*m),其中n是文本长度,m是关键词长度。
2. KMP算法
通过预处理关键词生成部分匹配表,避免无效回溯,时间复杂度为O(n+m),适合稍大一点的文本匹配场景。我们的简易模型可以优先使用朴素匹配算法,方便理解逻辑。
核心代码实现
文本预处理与索引构建
首先对导入的文本文件进行读取,然后按空格、标点分割为词语,构建倒排索引,记录每个词语出现在哪些文件中,以及出现次数。
import java.io.*;
import java.util.*;
// 简易搜索引擎模型核心类
public class SimpleSearchEngine {
// 存储倒排索引:key为词语,value为词语出现的文件及次数映射
private Map<String, Map<String, Integer>> invertedIndex = new HashMap<>();
// 存储文件原始内容,用于高亮展示
private Map<String, String> fileContentMap = new HashMap<>();
/**
* 导入文本文件构建索引
* @param filePath 文件路径
*/
public void addFile(String filePath) {
try {
File file = new File(filePath);
String fileName = file.getName();
BufferedReader reader = new BufferedReader(new FileReader(file));
StringBuilder content = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
content.append(line).append(" ");
}
reader.close();
// 存储文件原始内容
fileContentMap.put(fileName, content.toString());
// 分词处理,按空格、逗号、句号等分割
String[] words = content.toString().split("[\s+,\.,。!!??;;]+");
for (String word : words) {
if (word.isEmpty()) {
continue;
}
// 转为小写统一处理
word = word.toLowerCase();
// 更新倒排索引
Map<String, Integer> fileCountMap = invertedIndex.getOrDefault(word, new HashMap<>());
fileCountMap.put(fileName, fileCountMap.getOrDefault(fileName, 0) + 1);
invertedIndex.put(word, fileCountMap);
}
System.out.println("文件" + fileName + "导入完成,已构建索引");
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符串匹配查询实现
基于朴素匹配算法实现关键词查询,返回包含关键词的文件列表,同时统计每个文件中关键词的出现次数,并提供高亮处理方法。
/**
* 朴素字符串匹配方法
* @param text 待匹配文本
* @param pattern 关键词
* @return 关键词出现次数
*/
private int naiveMatch(String text, String pattern) {
int count = 0;
int textLen = text.length();
int patternLen = pattern.length();
if (patternLen == 0 || textLen < patternLen) {
return 0;
}
for (int i = 0; i <= textLen - patternLen; i++) {
boolean match = true;
for (int j = 0; j < patternLen; j++) {
if (text.charAt(i + j) != pattern.charAt(j)) {
match = false;
break;
}
}
if (match) {
count++;
i += patternLen - 1; // 匹配成功后跳过关键词长度,避免重复匹配
}
}
return count;
}
/**
* 搜索关键词,返回匹配结果
* @param keyword 用户输入的关键词
* @return 匹配结果列表,每个元素为文件名和匹配次数
*/
public List<Map.Entry<String, Integer>> search(String keyword) {
keyword = keyword.toLowerCase();
Map<String, Integer> result = new HashMap<>();
// 遍历所有文件内容,执行字符串匹配
for (Map.Entry<String, String> entry : fileContentMap.entrySet()) {
String fileName = entry.getKey();
String content = entry.getValue().toLowerCase();
int count = naiveMatch(content, keyword);
if (count > 0) {
result.put(fileName, count);
}
}
// 按匹配次数降序排序
List<Map.Entry<String, Integer>> sortedResult = new ArrayList<>(result.entrySet());
sortedResult.sort((a, b) -> b.getValue() - a.getValue());
return sortedResult;
}
/**
* 高亮文本中的关键词
* @param content 原始文本
* @param keyword 关键词
* @return 高亮后的文本
*/
public String highlightKeyword(String content, String keyword) {
String lowerContent = content.toLowerCase();
String lowerKeyword = keyword.toLowerCase();
StringBuilder result = new StringBuilder();
int lastIndex = 0;
for (int i = 0; i <= lowerContent.length() - lowerKeyword.length(); i++) {
boolean match = true;
for (int j = 0; j < lowerKeyword.length(); j++) {
if (lowerContent.charAt(i + j) != lowerKeyword.charAt(j)) {
match = false;
break;
}
}
if (match) {
// 拼接匹配前的文本
result.append(content, lastIndex, i);
// 拼接高亮的关键词,用strong标签包裹
result.append("<strong>").append(content, i, i + lowerKeyword.length()).append("</strong>");
lastIndex = i + lowerKeyword.length();
i += lowerKeyword.length() - 1;
}
}
// 拼接剩余文本
result.append(content, lastIndex, content.length());
return result.toString();
}
测试入口代码
编写测试类验证搜索引擎模型的功能是否正常。
public class SearchEngineTest {
public static void main(String[] args) {
SimpleSearchEngine engine = new SimpleSearchEngine();
// 导入测试文件,这里替换为实际的本地文件路径
engine.addFile("test1.txt");
engine.addFile("test2.txt");
// 搜索关键词
String keyword = "java";
System.out.println("搜索关键词:" + keyword);
List<Map.Entry<String, Integer>> results = engine.search(keyword);
if (results.isEmpty()) {
System.out.println("未找到匹配结果");
} else {
for (Map.Entry<String, Integer> entry : results) {
System.out.println("文件名:" + entry.getKey() + ",匹配次数:" + entry.getValue());
// 获取文件原始内容并高亮展示前100字符
String content = engine.fileContentMap.get(entry.getKey());
String highlight = engine.highlightKeyword(content.substring(0, Math.min(100, content.length())), keyword);
System.out.println("内容预览(高亮关键词):" + highlight);
System.out.println("------");
}
}
}
}
功能扩展方向
上述简易模型实现了基础搜索功能,还可以进一步扩展:
- 增加中文分词支持,使用开源分词库如HanLP处理中文文本
- 优化匹配算法为KMP或者Boyer-Moore算法,提升匹配效率
- 增加分页展示、搜索结果排序规则自定义等功能
- 支持多关键词联合查询,实现与、或、非逻辑检索
整个开发过程围绕Java字符串匹配技术展开,通过逐步搭建模块,就能实现基础的搜索引擎模型,帮助理解搜索引擎的核心运行逻辑。