Java开源分词系统IKAnalyzer学习(七) 词库加载分词

 

词库加载模块的源码:

Java开源分词系统IKAnalyzer学习(四) 词库加载源代码——Dictionary类

Java开源分词系统IKAnalyzer学习(五) 词库加载源代码——DictSegmenty类

Java开源分词系统IKAnalyzer学习(六) 词库加载源代码——Hit类

 

首先这个词典管理类Dictionary类采用的设计模式是单立模式,实现的代码:

 

[c-sharp]  view plain copy
 
  1. /* 
  2.  * 词典单子实例 
  3.  */  
  4. private static final Dictionary singleton;  
  5.   
  6. /* 
  7.  * 词典初始化 
  8.  */  
  9. static{  
  10.     singleton = new Dictionary();  
  11. }  
  12. private Dictionary(){  
  13.     //初始化系统词典  
  14.     loadMainDict();  
  15.     loadSurnameDict();  
  16.     loadQuantifierDict();  
  17.     loadSuffixDict();  
  18.     loadPrepDict();  
  19.     loadStopWordDict();  
  20. }  
  21. /** 
  22.  * 词典初始化 
  23.  * 由于IK Analyzer的词典采用Dictionary类的静态方法进行词典初始化 
  24.  * 只有当Dictionary类被实际调用时,才会开始载入词典, 
  25.  * 这将延长首次分词操作的时间 
  26.  * 该方法提供了一个在应用加载阶段就初始化字典的手段 
  27.  * 用来缩短首次分词时的时延 
  28.  * @return Dictionary 
  29.  */  
  30. public static Dictionary getInstance(){  
  31.     return Dictionary.singleton;  
  32. }  

 

 

 

词库加载的关键代码,这里以主词典为例,其他大同小异

 

[c-sharp]  view plain copy
 
  1.     /** 
  2.      * 加载主词典及扩展词典 
  3.      */  
  4.     private void loadMainDict(){  
  5.         //建立一个主词典实例  
  6.         _MainDict = new DictSegment((char)0);  
  7.         //读取主词典文件  
  8.         InputStream is = Dictionary.class.getResourceAsStream(Dictionary.PATH_DIC_MAIN);  
  9.         if(is == null){  
  10.             throw new RuntimeException("Main Dictionary not found!!!");  
  11.         }  
  12.           
  13.         try {  
  14.               
  15.             BufferedReader br = new BufferedReader(new InputStreamReader(is , "UTF-8"), 512);  
  16.             String theWord = null;  
  17.             do {  
  18.                 theWord = br.readLine();  
  19.                 //假如还没有读到文件尾  
  20.                 if (theWord != null && !"".equals(theWord.trim())) {  
  21.                     _MainDict.fillSegment(theWord.trim().toCharArray());  
  22.                 }  
  23.             } while (theWord != null);  
  24.               
  25.         } catch (IOException ioe) {  
  26.             System.err.println("Main Dictionary loading exception.");  
  27.             ioe.printStackTrace();  
  28.               
  29.         }finally{  
  30.             try {  
  31.                 if(is != null){  
  32.                     is.close();  
  33.                     is = null;  
  34.                 }  
  35.             } catch (IOException e) {  
  36.                 e.printStackTrace();  
  37.             }  
  38.         }  
  39. }  

 

 

 

底层的字典存储代码

 

[c-sharp]  view plain copy
 
  1. /** 
  2.  * 加载填充词典片段 
  3.  * @param charArray 
  4.  */  
  5. public void fillSegment(char[] charArray){  
  6.     this.fillSegment(charArray, 0 , charArray.length);   
  7. }  
  8.   
  9. /** 
  10.  * 加载填充词典片段 
  11.  * @param charArray 
  12.  * @param begin 
  13.  * @param length 
  14.  */  
  15. public synchronized void fillSegment(char[] charArray , int begin , int length){  
  16.     //获取字典表中的汉字对象  
  17.     Character beginChar = new Character(charArray[begin]);  
  18.     Character keyChar = charMap.get(beginChar);  
  19.     //字典中没有该字,则将其添加入字典  
  20.     if(keyChar == null){  
  21.         charMap.put(beginChar, beginChar);  
  22.         keyChar = beginChar;  
  23.     }  
  24.       
  25.     //搜索当前节点的存储,查询对应keyChar的keyChar,如果没有则创建(这段代码没看明白)  
  26.     DictSegment ds = lookforSegment(keyChar);  
  27.     //处理keyChar对应的segment  
  28.     if(length > 1){  
  29.         //词元还没有完全加入词典树  
  30.         ds.fillSegment(charArray, begin + 1, length - 1);  
  31.     }else if (length == 1){  
  32.         //已经是词元的最后一个char,设置当前节点状态为1,表明一个完整的词  
  33.         ds.nodeState = 1;  
  34.     }  
  35. }  
  36.   
  37. /** 
  38.  * 查找本节点下对应的keyChar的segment 
  39.  * 如果没有找到,则创建新的segment 
  40.  * @param keyChar 
  41.  * @return 
  42.  */  
  43. private DictSegment lookforSegment(Character keyChar){  
  44.       
  45.     DictSegment ds = null;  
  46.     if(this.storeSize <= ARRAY_LENGTH_LIMIT){  
  47.         //获取数组容器,如果数组未创建则创建数组  
  48.         DictSegment[] segmentArray = getChildrenArray();              
  49.         //搜寻数组  
  50.         for(DictSegment segment : segmentArray){  
  51.             if(segment != null && segment.nodeChar.equals(keyChar)){  
  52.                 //在数组中找到与keyChar对应的segment  
  53.                 ds =  segment;  
  54.                 break;  
  55.             }  
  56.         }             
  57.         //遍历数组后没有找到对应的segment  
  58.         if(ds == null){  
  59.             //构造新的segment  
  60.             ds = new DictSegment(keyChar);                
  61.             if(this.storeSize < ARRAY_LENGTH_LIMIT){  
  62.                 //数组容量未满,使用数组存储  
  63.                 segmentArray[this.storeSize] = ds;  
  64.                 //segment数目+1  
  65.                 this.storeSize++;  
  66.             }else{  
  67.                 //数组容量已满,切换Map存储  
  68.                 //获取Map容器,如果Map未创建,则创建Map  
  69.                 Map<Character , DictSegment> segmentMap = getChildrenMap();  
  70.                 //将数组中的segment迁移到Map中  
  71.                 migrate(segmentArray ,  segmentMap);  
  72.                 //存储新的segment  
  73.                 segmentMap.put(keyChar, ds);  
  74.                 //segment数目+1 ,  必须在释放数组前执行storeSize++ , 确保极端情况下,不会取到空的数组  
  75.                 this.storeSize++;  
  76.                 //释放当前的数组引用  
  77.                 this.childrenArray = null;  
  78.             }  
  79.         }             
  80.           
  81.     }else{  
  82.         //获取Map容器,如果Map未创建,则创建Map  
  83.         Map<Character , DictSegment> segmentMap = getChildrenMap();  
  84.         //搜索Map  
  85.         ds = (DictSegment)segmentMap.get(keyChar);  
  86.         if(ds == null){  
  87.             //构造新的segment  
  88.             ds = new DictSegment(keyChar);  
  89.             segmentMap.put(keyChar , ds);  
  90.             //当前节点存储segment数目+1  
  91.             this.storeSize ++;  
  92.         }  
  93.     }  
  94.     return ds;  
  95. }  

 

 http://blog.csdn.net/lengyuhong/article/details/6010123

你可能感兴趣的:(Java开源分词系统IKAnalyzer学习(七) 词库加载分词)