首先介绍一下IK Analyzer
IK Analyzer是一个开源的、基于java语言开发的轻量级中文分词工具包。已经推出了4个大版本。从3.0版本开始,IK Analyzer发展为面向java的公用分词组件,独立于lucene项目,同时提供了对lucene的默认优化实现。在2012版本中,IK Analyzer实现了简单的分词歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。支持细粒度ik_max_word和智能分词ik_smart两种切分模式。
其项目地址为:https://code.google.com/archive/p/ik-analyzer/downloads
下载2012版本source,可以看到其是兼容lucene3.1以上版本的
lucene6.0使用IK分词器需要修改IKAnalyzer和IKTokenizer。
IKAnalyzer的修改,重写最新版本的CreateComponents方法;重载Analyzer接口
public class IKAnalyzer6x extends Analyzer {
private boolean useSmart;
public boolean useSmart() {
return useSmart;
}
public void setUseSmart(boolean useSmart) {
this.useSmart = useSmart;
}
// IK分词器Lucene Analyzer接口实现类;默认细粒度切分算法
public IKAnalyzer6x() {
this(false);
}
// IK分词器Lucene Analyzer接口实现类;当为true时,分词器进行智能切分
public IKAnalyzer6x(boolean useSmart) {
super();
this.useSmart = useSmart;
}
// 重写最新版本的createComponents;重载Analyzer接口,构造分词组件
@Override
protected TokenStreamComponents createComponents(String fieldName) {
Tokenizer _IKTokenizer = new IKTokenizer6x(this.useSmart());
return new TokenStreamComponents(_IKTokenizer);
}
}
IKTokenizer的修改,要实现最新的Tokenizer接口
public class IKTokenizer6x extends Tokenizer {
// IK分词器实现
private IKSegmenter _IKImplement;
// 词元文本属性
private final CharTermAttribute termAtt;
// 词元位移属性
private final OffsetAttribute offsetAtt;
// 词元分类属性(该属性分类参考org.wltea.analyzer.core.Lexeme中的分类常量)
private final TypeAttribute typeAtt;
// 记录最后一个词元的结束位置
private int endPosition;
// Lucene 6.x Tokenizer适配器类构造函数;实现最新的Tokenizer接口
public IKTokenizer6x(boolean useSmart) {
super();
offsetAtt = addAttribute(OffsetAttribute.class);
termAtt = addAttribute(CharTermAttribute.class);
typeAtt = addAttribute(TypeAttribute.class);
_IKImplement = new IKSegmenter(input, useSmart);
}
@Override
public boolean incrementToken() throws IOException {
// 清除所有的词元属性
clearAttributes();
Lexeme nextLexeme = _IKImplement.next();
if (nextLexeme != null) {
// 将Lexeme转成Attributes
// 设置词元文本
termAtt.append(nextLexeme.getLexemeText());
// 设置词元长度
termAtt.setLength(nextLexeme.getLength());
// 设置词元位移
offsetAtt.setOffset(nextLexeme.getBeginPosition(), nextLexeme.getEndPosition());
// 记录分词的最后位置
endPosition = nextLexeme.getEndPosition();
// 记录词元分类
typeAtt.setType(nextLexeme.getLexemeText());
// 返会true告知还有下个词元
return true;
}
// 返会false告知词元输出完毕
return false;
}
@Override
public void reset() throws IOException {
super.reset();
_IKImplement.reset(input);
}
@Override
public final void end() {
int finalOffset = correctOffset(this.endPosition);
offsetAtt.setOffset(finalOffset, finalOffset);
}
}
以上都来自姚潘《从lucene到ElasticSearch全文检索实战》
如果在使用中出现错误
java.lang.AssertionError: TokenStream implementation classes or at least their incrementToken() implementation must be final
那么为IKTokenizer6x class 加入final关键字
如何把lucene ik analyzer引入到我的maven项目中呢?
当然,基础是pom.xml中加入了lucene依赖
<!--搜索引擎lucene-->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queries</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-smartcn</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>2.5.1</version>
</dependency>
接下来需要把IK Analysis使用的jar包加入到Intellij idea项目中
通过Project Structure – module –Dependencies,加入对应文件夹
其lib下放我们下载的IK Analyzer jar包
接下来在项目中新建文件夹ik,里面放我们重写的IKAnalyzer6x及IKTokenizer6x java文件
最后把词典等配置文件放到classpath路径下,即resources中
这样我们在程序中就可以使用IKAnalyzer6x分词器了
我们在pom中添加了lucene官方的lucene-analyzers-smartcn分词器
下面程序比较了IK分词与Smartcn分词的效果
public class IkVSSmartcn {
private static String str2 = "IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。";
public static void main(String[] args) {
Analyzer analyzer = null;
System.out.println("-------------------------------------------");
System.out.println("句子2:"+str2);
System.out.println("SmartChineseAnalyzer分词结果:");
analyzer = new SmartChineseAnalyzer();
printAnalyzer(analyzer, str2);
System.out.println("IKAnalyzer分词结果:");
analyzer = new IKAnalyzer6x(true);
printAnalyzer(analyzer, str2);
}
public static void printAnalyzer(Analyzer analyzer, String str) {
StringReader reader = new StringReader(str);
//处理单个字符组成的字符流,读取Reader对象中的数据,处理后转换成词汇单元
TokenStream tokenStream = analyzer.tokenStream(str, reader);
// 清空流
try {
tokenStream.reset();
} catch (IOException e) {
e.printStackTrace();
}
//CharTermAttribute -- The term text of a Token.
//Returns the instance of the passed in Attribute contained in this AttributeSource
CharTermAttribute attribute = tokenStream.getAttribute(CharTermAttribute.class);
try {
while (tokenStream.incrementToken()) {
System.out.print(attribute.toString()+"|");
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println();
}
}
结果
句子2:IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。
SmartChineseAnalyzer分词结果:
ikanalyz|是|一个|开|源|的|基于|java|语言|开发|的|轻量级|的|中文|分词|工具包|
IKAnalyzer分词结果:
加载扩展词典:ext.dic
加载扩展停止词典:stopword.dic
加载扩展停止词典:ext_stopword.dic
ikanalyzer|开源|java|语言|开发|轻量级|中文|分词|工具包|
看起来IK分词效果更好