IK分词源代码分析学习——子分词器 http://blog.chinaunix.net/uid-20761674-id-3424176.html

IK分词源代码分析学习——歧义处理 http://blog.chinaunix.net/uid-20761674-id-3424553.html

 

创建ik对象时,调用IKSegmenter类的构造函数进行初始化

IKSegmenter ik=new IKSegmenter(sr, false);  //true代表调用IKSegmenter()构造函数时使用智能分词

 

构造函数如下:

public IKSegmenter(Reader input , boolean useSmart){
        this.input = input;
        this.cfg = DefaultConfig.getInstance();
        this.cfg.setUseSmart(useSmart);
        this.init();
    }

 

this.cfg = DefaultConfig.getInstance();初始化配置文件

public static Configuration getInstance(){
        return new DefaultConfig();
    }
        
    /*
     * 初始化配置文件
     */
    private DefaultConfig(){        
        props = new Properties();
        
        InputStream input = this.getClass().getClassLoader().getResourceAsStream(FILE_NAME);
        if(input != null){
            try {
                props.loadFromXML(input);
            } catch (InvalidPropertiesFormatException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

 

this.cfg.setUseSmart(useSmart);设置useSmart标志位

/**
     * 设置useSmart标志位
     * useSmart =true ,分词器使用智能切分策略, =false则使用细粒度切分
     * @param useSmart
     */
    public void setUseSmart(boolean useSmart) {
        this.useSmart = useSmart;
    }    

this.init()初始化
private void init(){
        //初始化词典单例
        Dictionary.initial(this.cfg);
        //初始化分词上下文
        this.context = new AnalyzeContext(this.cfg);
        //加载子分词器
        this.segmenters = this.loadSegmenters();
        //加载歧义裁决器
        this.arbitrator = new IKArbitrator();
    }

 

Dictionary.initial(this.cfg);

/**
     * 词典初始化
     * 由于IK Analyzer的词典采用Dictionary类的静态方法进行词典初始化
     * 只有当Dictionary类被实际调用时,才会开始载入词典,
     * 这将延长首次分词操作的时间
     * 该方法提供了一个在应用加载阶段就初始化字典的手段
     * @return Dictionary
     */
    public static Dictionary initial(Configuration cfg){
        if(singleton == null){
            synchronized(Dictionary.class){
                if(singleton == null){
                    singleton = new Dictionary(cfg);
                    return singleton;
                }
            }
        }
        return singleton;
    }
private Dictionary(Configuration cfg){
        this.cfg = cfg;
        //建立一个主词典实例
        _MainDict = new DictSegment((char)0);
        this.loadMainDict(_MainDict);
/*_StopWordDict = new DictSegment((char)0); this.loadStopWordDict(_StopWordDict);*/ this.loadQuantifierDict();
this.loadCharFreqDict(); }
private void loadMainDict(DictSegment dstDicSegment){
        
        //读取主词典文件
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(cfg.getMainDictionary());
        if(inputStream == null){
            throw new RuntimeException("Main Dictionary not found!!!");
        }
        
        System.out.println("test加载主字典");
        this.loadWords2DictSegment(inputStream,dstDicSegment);
       
        
        System.out.println("test加载扩展字典");
        this.loadExtDict(dstDicSegment);
       
    }    

这里在初始化的时候将主词典和扩展词典一起加载到_MainDict中进行匹配计算,所以若想要实现只加载一个词典可以在这里进行,但由于是在构造其中初始化的时候加载的,就无法根据情况判断是否加载或加载那个词典

private void loadQuantifierDict(){
        //建立一个量词典实例
        _QuantifierDict = new DictSegment((char)0);
        //读取量词词典文件
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(cfg.getQuantifierDicionary());
        if(is == null){
            throw new RuntimeException("Quantifier Dictionary not found!!!");
        }
        loadWords2DictSegment(is, _QuantifierDict);
        System.out.println("加载量词词典");
    }

加载完词典后,便完成了初始化初始化词典单例,跳入初始化分词上下文,然后

加载子分词器this.segmenters = this.loadSegmenters();

private List<ISegmenter> loadSegmenters(){
        List<ISegmenter> segmenters = new ArrayList<ISegmenter>(4);
        //处理字母的子分词器
        segmenters.add(new LetterSegmenter()); 
        //处理中文数量词的子分词器
        segmenters.add(new CN_QuantifierSegmenter());
        //处理中文词的子分词器
        segmenters.add(new CJKSegmenter());
        return segmenters;
    }

加载歧义裁决器

到此,就完成了IKSegmenter ik=new IKSegmenter(sr, false);

进入ik.next()函数的调用,进入分词的主流程(见IK分词源代码分析学习——总体流程



 
 posted on 2013-11-27 21:08  瞌睡的美人鱼  阅读(940)  评论(0编辑  收藏  举报