【转载保存】修改IK分词器源码实现动态加载词典

链接:http://www.gongstring.com/portal/article/index/id/59.html

当前IKAnalyzer从发布最后一个版本后就一直没有再更新,使用过程中,经常遇到需要扩展词库以及动态更新字典表的问题,此处给出一种解决办法(注意:本方法中的IKAnalyzer代码我已经将源码移植到了自己的工程中,目录结构也进行了修改):

 

1、将扩展字典表做成可动态生成:

 1)、在IKAnalyzer.cfg.xml中添加扩展字典路径

    blob.png

 2)、在分词的时候,先采取动态生成上面两个字典表的方式进行更新,例如事先将字典词库放在数据表中,需要分词之前先更新字典。当然此方法只支持第一次调用的时候动态加载词库,如果服务没有重启之前,数据库中添加的词是不会进行重新加载的。下面是动态生成字典表的实现类:

package com.chz.apps.sm.IKAnalyzer;import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;import com.chz.apps.sm.model.IkanalyzerExtendModel;
import com.chz.base.util.FileUtil;
import com.chz.plugin.IKAnalyzer.core.IKSegmenter;
import com.chz.plugin.IKAnalyzer.core.Lexeme;/*** @Description 分词工具类* @author gongstring<1@gongstring.com>* @createTime 2016年11月28日 下午2:46:06*/
public class IKAnalyzerTool {/*** 是否已经初始化过词库,如果没有,则会自动先调用词库*/private static boolean init_words = false;/*** 扩展关键字*/private static List<String> extendWords = new ArrayList<String>();/*** 停用关键字*/private static List<String> stopWords = new ArrayList<String>();/*** @Description 初始化词库以及停用词* @author gongstring<1@gongstring.com>* @createTime 2016年11月28日 下午2:29:59*/public static void initWords(){//从关键字表中查询扩展关键字,并生成到指定文件中IKAnalyzerTool.extendWords = new ArrayList<String>();List<IkanalyzerExtendModel> extendWords = IkanalyzerExtendModel.dao.findByProperty("status", 1);String fileDirPath = IKAnalyzerTool.class.getResource("/com/chz/apps/sm/IKAnalyzer/").getPath();String filePath = fileDirPath+"extend.dic";FileUtil.removeFile(filePath);//先删除文件,此处重新生成for (int i = 0; i < extendWords.size(); i++) {String txt = extendWords.get(i).getStr("extend_word");FileUtil.appendToFile(filePath, txt,true);IKAnalyzerTool.extendWords.add(txt);}//从关键字表中查询停用关键字,并生成到指定文件中IKAnalyzerTool.stopWords = new ArrayList<String>();List<IkanalyzerExtendModel> stopWords = IkanalyzerExtendModel.dao.findByProperty("status", 0);String stopFilePath = fileDirPath+"stopword.dic";FileUtil.removeFile(stopFilePath);//先删除文件,此处重新生成for (int i = 0; i < stopWords.size(); i++) {String txt = stopWords.get(i).getStr("extend_word");FileUtil.appendToFile(stopFilePath, txt,true);IKAnalyzerTool.stopWords.add(txt);}init_words = true;}/*** @Description 分词操作* @author gongstring<1@gongstring.com>* @createTime 2016年11月28日 下午3:30:10* @param str* @param justExist 是否只显示已经在词库中维护了的关键词* @return*/public static List<String> IKAnalysis(String str,boolean justExist) {List<String> tmp = IKAnalysis(str);List<String> result = new ArrayList<String>();if(justExist){for (int i = 0; i < tmp.size(); i++) {if(IKAnalyzerTool.extendWords.contains(tmp.get(i))){result.add(tmp.get(i));}}}else{result = tmp;}return result;}/*** @Description 根据字符串自动拆分成关键字集合* @author gongstring<1@gongstring.com>* @createTime 2016年11月28日 下午2:55:24* @param str* @return*/public static List<String> IKAnalysis(String str) {if(!init_words){initWords();}List<String> result = new ArrayList<String>();try {// InputStream in = new FileInputStream(str);//byte[] bt = str.getBytes();// strInputStream ip = new ByteArrayInputStream(bt);Reader read = new InputStreamReader(ip);IKSegmenter iks = new IKSegmenter(read, true);Lexeme t;while ((t = iks.next()) != null) {result.add(t.getLexemeText());}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return result;}}

 

2、修改源码,实现动态更新字典表。通过查看源码IKAnalyzer.dic.Dictionary.java文件得出,字典对象是采取单例模式,也就是第一次加载后,后续不在重新加载,这样即使字典表内容变化,缓存中的字典库是不会变更的,所以需要修改源码,可以手动更新单例对象的内容,此处我采取添加clear方法,在需要更新时候调用,将instance对象设置为null,下次调用字典的时候,程序就会自动加载了

	/*** @Description 清空字典缓存,用于动态更新字典表* @author gongstring<1@gongstring.com>* @createTime 2016年11月29日 上午9:56:15*/public static void clear(){singleton = null;}

 

blob.png

 

源码修改完后,可以选择编译重新打包,或者将jar包中的class文件删除,java类在工程中按照源目录存放。

3、手动调用,我这里是做的一个页面,点击更新字典库时,调用更新代码:

	/*** @Description 刷新关键词缓存* @author gongstring<1@gongstring.com>* @createTime 2016年11月29日 上午9:33:49*/public void refreshCache(){IKAnalyzerTool.initWords();//重新加载词汇Dictionary.clear();//将字典表缓存清空this.renderSuccessJson(EnvConfig.APP_PATH+"/sm/ikanalyzerExtend");}

 

4、可能存在的性能问题:由于词库一般会比较大,所以每次大批量更新可能会出现性能损耗。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508907.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转载保存】索引文件锁LockFactory

索引文件锁LockFactory LockFactory在Lucene中用来对索引文件所在的目录进行加锁&#xff0c;使得同一时间总是只有一个IndexWriter对象可以更改索引文件&#xff0c;即保证单进程内(single in-process)多个不同IndexWriter对象互斥更改&#xff08;多线程持有相同引用的IndexW…

IndexOptions类说明

IndexOptions是在lucene-core-x.jar包下面&#xff0c;其作用是在新建索引时候选择索引属性。 IndexOptions是一个枚举类&#xff1a; 枚举变量说明&#xff1a; NONE不被索引DOCS_AND_FREQS文档和词频建立索引DOCS_AND_FREQS仅对文档和词频建立索引DOCS_AND_FREQS_AND_POSIT…

【转载保存】lucene正则查询使用注意

今天要分享的是关于lucene中另外一种丰富的查询方式----正则查询&#xff0c;lucene内置了许多的查询API&#xff0c;以及更强大的自定义查询方式的QueryParse&#xff0c;大部分情况下我们使用内置的查询API&#xff0c;基本上就可以满足我们的需求了&#xff0c;但是如果你想…

【转载保存】搜索引擎调研文档

搜索引擎选型调研文档 Elasticsearch简介* Elasticsearch是一个实时的分布式搜索和分析引擎。它可以帮助你用前所未有的速度去处理大规模数据。 它可以用于全文搜索&#xff0c;结构化搜索以及分析&#xff0c;当然你也可以将这三者进行组合。 Elasticsearch是一个建立在全…

lucene详细说明文档

以下部门功能在lucene5以上版本可能有的API所有改变 目录1.简介 2.了解索引操作 2.1倒排索引 2.2字段类型 2.3细分 2.4文件编号 2.5搜索索引 3.创建索引 4.基本索引操作 4.1核心索引类 4.2将数据添加到索引 5.文件和领域 5.1文件 5.2领域 5.3在Lucene中增强文档 1.简介 该索引是…

分布式集群架构场景解决方案学习笔记

课程学习 一致性哈希算法集群时钟同步问题分布式ID解决方案分布式任务调度问题session共享(一致性)问题 一致性哈希算法 一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式Cache中提出的&#xff0c;设计目标是为了解决因特网中的热点(Hot spot)问题&#xff0c…

分布式学习-总结

文章目录分布式理论分布式系统定义以及面临的问题分布式系统定义分布式面临的问题通信异常网络分区三态节点故障分布式理论&#xff1a;一致性概念分布式一致性的提出强一致性弱一致性最终一致性分布式事务CAP定理什么是CAP理论&#xff1f;为什么只能3选2能不能解决3选2的问题…

什么叫死锁?死锁案例?死锁必须满足哪些条件?如何定位死锁问题?有哪些解决死锁策略?哲学家问题?

1.死锁是什么&#xff1f; 死锁一定发生在并发环境中&#xff0c;死锁是一种状态&#xff0c;当两个(或者多个线程)相互持有对方所需要的资源&#xff0c;却又都不主动释放手中持有的资源&#xff0c;导致大家都获取不到自己想要的资源&#xff0c;所有相关的线程无法继续执行…

dubbo启动服务启动报错.UnsatisfiedDependencyException: Error creating bean with name '***': Un

报错信息&#xff1a; 今天部署开发环境的时候这个问题弄了一下午&#xff0c;由于我本地启动是好的&#xff0c;然后部署到服务器老是启动不了&#xff0c;报如上错&#xff0c;后来经过排查发现是provider.xml和consumer.xml中的如下代码version属性版本信息不一致。 <du…

【转载保存】dubbo学习笔记

Dubbo Dubbo简介 首先&#xff0c;我理解的Dubbo&#xff0c;从大的方向来看是单体应用到分布式应用过度期的一个产物&#xff0c;具体来说应该是分布式应用从早期的SOA到微服务过度的一个产物。 在编写分布式场景下高并发、高扩展的系统对技能的要求很高&#xff0c;因为这…

mysql搭建手册

mysql搭建手册 主从搭建 搭建mysql 关闭防火墙&#xff1a;systemctl stop firewalld 如果失败先安装 yum install iptables-services 配置数据库 /etc/my.cnf&#xff0c;配置同步数据库等 主库配置信息 [mysqld] datadir/usr/local/mysql/data log-error/usr/local/mysql/…

MongoDb安装配置

Mongodb学习 Mongodb安装 1.下载社区版 MongoDB 4.1.3 去官网下载对应的MongoDB 然后上传到Linux虚拟机 2.将压缩包解压即可 tar -zxvf MongoDB-linux-x86_64-4.1.3.tgz3.启动 mkdir -p /data/db./bin/mongod4.指定配置文件方式的启动 配置文件样例: dbpath/data/mongo…

FastDFS学习笔记

FastDFS课程内容 第一部分&#xff1a;FastDFS基础回顾 为什么要有分布式文件系统、分布式文件系统对比、FastDFS特性、linux安装、java访问FastDFS 第二部分&#xff1a;FastDFS系统架构和功能原理 架构详解、架构设计的概念、设计理念、功能原理(上传、下载、文件同步、删…

redis主从搭建和分片集群搭建

文章目录redis主从搭建搭建一主一从&#xff1a;下载安装redis&#xff1a;两台机器都需要操作权限认证理解主从复制原理、同步数据集全量同步三个阶段&#xff1a;增量同步&#xff1a;心跳检测redis哨兵模式部署方案搭建配置哨兵模式原理建立连接获取主服务器信息获取从服务器…

如何利用redis实现秒杀系统

文章目录题记利用Watch实现Redis乐观锁题记 在线思维导图总结&#xff1a;redis大纲 利用Watch实现Redis乐观锁 乐观锁基于CAS&#xff08;Compare And Swap&#xff09;思想&#xff08;比较并替换&#xff09;&#xff0c;是不具有互斥性&#xff0c;不会产生锁等待而消 耗…

教你如何使用redis分布式锁

文章目录一、redis客户端实现应用1.利用set nx命令实现分布式锁2.利用分布式锁命令 setnx问题1.为什么不直接调用jedis.del(key)方法而采用redislua实现&#xff1f;2.上述两种方式存在的问题&#xff1f;3.根本原因分析二、分布式场景Redission分布式锁的使用1.分布式锁的特性…

本地缓存之Guava简单使用

文章目录使用场景Guava Cache 的优势Guava Cache使用CacheLoaderCallable删除主动删除过期删除基于容量删除引用删除高级用法并发设置更新锁定GuavaCache高级实战之疑难问题GuavaCache会oom&#xff08;内存溢出&#xff09;吗GuavaCache缓存到期就会立即清除吗GuavaCache如何找…

java中强引用、弱引用、软引用、虚引用学习

文章目录强引用弱引用软引用虚引用将引用之前首先让我们一起回顾一下java对象的生命周期强引用 在实际开发场景中&#xff0c;我们一般使用的都是强引用&#xff0c;只要强引用存在&#xff0c;垃圾回收即使OOM也不会回收&#xff0c;知道强引用释放以后&#xff0c;对象才会被…

mysql left join、right join、inner join、union、union all使用以及图解

左外连接&#xff1a;left join sql语法&#xff1a;LEFT JOIN LEFT OUTER JOIN 首先需要创建两张表做测试&#xff0c;表数据如下所示 table 1 表&#xff1a; table2 表&#xff1a; 查询sql&#xff1a; select * from table1 a LEFT JOIN table2 b on a.idb.id 总结&a…

第十八章 Swing程序设计

Swing用于开发桌面窗体程序&#xff0c;是JDK的第二代GUI框架&#xff0c;其功能比JDK第一代GUI框架AWT更为强大、性能更加优良。但因为Swing技术推出时间太早&#xff0c;其性能、开发效率等不及一些其他流行技术&#xff0c;所以目前市场上大多数桌面窗体程序都不是由Java开发…