Lucene 分词

在Lucene中很多数据是通过Attribute进行存储的

 步骤是同过TokenStrem获取文本信息流

TokenStream stream = a.tokenStream("content", new StringReader(str)); (a:指的是Analyzer)

而在这里对这个由不同的分词的话之需要实现Analyer,并重写里面的tokenStream 方法

public TokenStream tokenStream(String fieldName, Reader reader) {
Dictionary dic = Dictionary.getInstance("F:\CheckOut\Lucene\03_lucene_analyzer\mmseg4j-1.8.4\data");

return new MySameTokenFilter(new MMSegTokenizer(new MaxWordSeg(dic), reader),samewordContext);
}

然后这里获取他的Tokenizer 并可以实现自己的过滤器,以及相应的同义词删减

public class MySameTokenFilter extends TokenFilter{

    private CharTermAttribute cta = null;
    private PositionIncrementAttribute pia = null;
    private AttributeSource.State current = null;
    private Stack<String> sames = null;
    private SamewordContext samewordContext;
    
    protected MySameTokenFilter(TokenStream input,SamewordContext samewordContext) {
        super(input);
        cta = this.addAttribute(CharTermAttribute.class);
        pia = this.addAttribute(PositionIncrementAttribute.class);
        sames = new Stack<String>();
        this.samewordContext=samewordContext;
    }

    /**
     * 思想如下:
     * 其实每个同义词都要放在CharTermAttribute里面,但是如果直接cta.append("大陆");的话
     * 那会直接把原来的词和同义词连接在同一个语汇单元里面[中国大陆],这样是不行的
     * 要的是这样的效果[中国][大陆]
     * 那么就要在遇到同义词的时候把当前的状态保存一份,并把同义词的数组放入栈中,
     * 这样在下一个语汇单元的时候判断同义词数组是否为空,不为空的话把之前的保存的一份状态
     * 还原,然后在修改之前状态的值cta.setEmpty(),然后在把同义词的值加入cta.append("大陆")
     * 再把位置增量设为0,pia.setPositionIncrement(0),这样的话就表示是同义词,
     * 接着把该同义词的语汇单元返回
     */
    @Override
    public boolean incrementToken() throws IOException {
        System.out.println("yaobo");
        while(sames.size() > 0){
            //将元素出栈,并获取这个同义词
            String str = sames.pop();
            //还原状态
            restoreState(current);
            cta.setEmpty();
            cta.append(str);
            //设置位置
            pia.setPositionIncrement(0);
            return true;
        }
        if(!input.incrementToken()) return false;
        if(addSames(cta.toString())){
            //如果有同义词将当前状态先保存
            current = captureState();
        }
        return true;
    }
/*    
 * 使用这种方式是不行的,这种会把的结果是[中国]替换成了[大陆]
 * 而不是变成了[中国][大陆]
    @Override
    public boolean incrementToken() throws IOException {
        if(!input.incrementToken()) return false;
        if(cta.toString().equals("中国")){
            cta.setEmpty();
            cta.append("大陆");
        }
        return true;
    }
*/
    private boolean addSames(String name){
        
        String[] sws = samewordContext.getSamewords(name);
        if(sws != null){
            for(String s : sws){
                sames.push(s);
            }
            return true;
        }
        return false;
    }
}

其思想如下

然后通过不同的Attribute进行分割

TokenStream stream = a.tokenStream("content", new StringReader(str));
//位置增量
PositionIncrementAttribute pia = stream.addAttribute(PositionIncrementAttribute.class);
//偏移量
OffsetAttribute oa = stream.addAttribute(OffsetAttribute.class);
//词元
CharTermAttribute cta = stream.addAttribute(CharTermAttribute.class);
//分词的类型
TypeAttribute ta = stream.addAttribute(TypeAttribute.class);

原文地址:https://www.cnblogs.com/yaobolove/p/6896883.html