Apache Lucene 5.x 集成中文分词库 IKAnalyzer
前面写过 Apache Lucene 5.x版本 示例,为了支持中文分词,我们可以使用中文分词库 IKAnalyzer。
由于IKAnalyzer使用的是4.x版本的Analyzer接口,该接口和5.x版本不兼容,因此,如果想要在5.x版本中使用IKAnalyzer,我们还需要自己来实现5.x版本的接口。
通过看源码,发现需要修改两个接口的类。
第一个是Tokenizer
接口,我们写一个IKTokenizer5x
:
/** * 支持5.x版本的IKTokenizer * * @author liuzh */ public class IKTokenizer5x extends Tokenizer { private IKSegmenter _IKImplement; private final CharTermAttribute termAtt = (CharTermAttribute)this.addAttribute(CharTermAttribute.class); private final OffsetAttribute offsetAtt = (OffsetAttribute)this.addAttribute(OffsetAttribute.class); private final TypeAttribute typeAtt = (TypeAttribute)this.addAttribute(TypeAttribute.class); private int endPosition; public IKTokenizer5x() { this._IKImplement = new IKSegmenter(this.input, true); } public IKTokenizer5x(boolean useSmart) { this._IKImplement = new IKSegmenter(this.input, useSmart); } public IKTokenizer5x(AttributeFactory factory) { super(factory); this._IKImplement = new IKSegmenter(this.input, true); } public boolean incrementToken() throws IOException { this.clearAttributes(); Lexeme nextLexeme = this._IKImplement.next(); if(nextLexeme != null) { this.termAtt.append(nextLexeme.getLexemeText()); this.termAtt.setLength(nextLexeme.getLength()); this.offsetAtt.setOffset(nextLexeme.getBeginPosition(), nextLexeme.getEndPosition()); this.endPosition = nextLexeme.getEndPosition(); this.typeAtt.setType(nextLexeme.getLexemeTypeString()); return true; } else { return false; } } public void reset() throws IOException { super.reset(); this._IKImplement.reset(this.input); } public final void end() { int finalOffset = this.correctOffset(this.endPosition); this.offsetAtt.setOffset(finalOffset, finalOffset); } }
该类只是在IKTokenizer
基础上做了简单修改,和原方法相比修改了public IKTokenizer(Reader in, boolean useSmart)
这个构造方法,不在需要Reader
参数。
另一个接口就是Analyzer
的IKAnalyzer5x
:
/** * 支持5.x版本的IKAnalyzer * * @author liuzh */ public class IKAnalyzer5x extends Analyzer { private boolean useSmart; public boolean useSmart() { return this.useSmart; } public void setUseSmart(boolean useSmart) { this.useSmart = useSmart; } public IKAnalyzer5x() { this(false); } public IKAnalyzer5x(boolean useSmart) { this.useSmart = useSmart; } @Override protected TokenStreamComponents createComponents(String fieldName) { IKTokenizer5x _IKTokenizer = new IKTokenizer5x(this.useSmart); return new TokenStreamComponents(_IKTokenizer); } }
这个类的接口由 protected TokenStreamComponents createComponents(String fieldName, Reader in)
变成了 protected TokenStreamComponents createComponents(String fieldName)
方法的实现中使用了上面创建的IKTokenizer5x
。
定义好上面的类后,在Lucene中使用IKAnalyzer5x
即可。
针对IKAnalyzer5x
我们写个简单测试:
/** * IKAnalyzer5x 测试 * * @author liuzh */ public class IKAnalyzer5xTest { public static void main(String[] args) throws IOException { Analyzer analyzer = new IKAnalyzer5x(true); TokenStream ts = analyzer.tokenStream("field", new StringReader( "IK Analyzer 是一个开源的,基于java语言开发的轻量级的中文分词工具包。" + "从2006年12月推出1.0版开始, IKAnalyzer已经推出了4个大版本。" + "最初,它是以开源项目Luence为应用主体的," + "结合词典分词和文法分析算法的中文分词组件。从3.0版本开始," + "IK发展为面向Java的公用分词组件,独立于Lucene项目," + "同时提供了对Lucene的默认优化实现。在2012版本中," + "IK实现了简单的分词歧义排除算法," + "标志着IK分词器从单纯的词典分词向模拟语义分词衍化。")); OffsetAttribute offsetAtt = ts.addAttribute(OffsetAttribute.class); try { ts.reset(); while (ts.incrementToken()) { System.out.println(offsetAtt.toString()); } ts.end(); } finally { ts.close(); } } }
输出结果:
ik analyzer 是 一个 开源 的 基于 java 语言 开发 的 轻量级 的 中文 分词 工具包 从 2006年 12月 推出 1.0版
由于结果较长,省略后面的输出内容。