当前位置: 首页 > news >正文

自己写Lucene分词器原理篇——CJKAnalyzer简单讲解

其中CJK中日韩统一表意文字(CJK Unified Ideographs),目的是要把分别来自中文、日文、韩文、越文中,本质、意义相同、形状一样或稍异的表意文字(主要为汉字,但也有仿汉字如日本国字、韩国独有汉字、越南的喃字)于ISO 10646及Unicode标准内赋予相同编码。CJK 是中文(Chinese)、日文(Japanese)、韩文(Korean)三国文字的缩写。顾名思义,它能够支持这三种文字。

实际上,CJKAnalyzer支持中文、日文、韩文和朝鲜文。

CJKAnalyzer的所有类:


CJKAnalyzer是主类

CJKWidthFilter是负责格式化字符,主要是折叠变种的半宽片假名成等价的假名

CJKBigramFilter是负责把两个CJK字符切割成两个,只要是CJK字符就会两两切割,ABC->AB,BC

CJKTokenizer是兼容低版本的分析器

1.CJKAnalyzer的主要部分,可以看出,先判断版本号,低版本直接用CJKTokenizer,高版本的先用standardanalyzer把非英文字母数字一个个分开,再用CJKWidthFilter格式化CJK字符,再用LowerCaseFilter转换英文成小写,再用CJKBigramFilter把CJK字符切割成两两的。

protected TokenStreamComponents createComponents(String fieldName,
      Reader reader) {
    if (matchVersion.onOrAfter(Version.LUCENE_36)) {
      final Tokenizer source = new StandardTokenizer(matchVersion, reader);
      // run the widthfilter first before bigramming, it sometimes combines characters.
      TokenStream result = new CJKWidthFilter(source);
      result = new LowerCaseFilter(matchVersion, result);
      result = new CJKBigramFilter(result);
      return new TokenStreamComponents(source, new StopFilter(matchVersion, result, stopwords));
    } else {
      final Tokenizer source = new CJKTokenizer(reader);
      return new TokenStreamComponents(source, new StopFilter(matchVersion, source, stopwords));
    }
  }
2. CJKWidthFilter的部分主要是折叠变种的半宽片假名成等价的假名,有点类似全角符号转换成半角符号,含义是一样的,但是表示不一样,主要针对日文。

3.CJKBigramFilter,该fileter可以选择既输出单字切割,同时也输出双字切割;或者只输出双字切割

public boolean incrementToken() throws IOException {
    while (true) {
    //判断之前是否暂存了双CJK字符 
       if (hasBufferedBigram()) {
        
        // case 1: we have multiple remaining codepoints buffered,
        // so we can emit a bigram here.
        //如果选择了要输出单字切割
        if (outputUnigrams) {

          // when also outputting unigrams, we output the unigram first,
          // then rewind back to revisit the bigram.
          // so an input of ABC is A + (rewind)AB + B + (rewind)BC + C
          // the logic in hasBufferedUnigram ensures we output the C, 
          // even though it did actually have adjacent CJK characters.

          if (ngramState) {
            flushBigram();//写双字
          } else {
            flushUnigram();//写单字,然后后退一个字符(rewind)
            index--;
          }
         //这个个对应上面的判断,实现双字输出
          ngramState = !ngramState;
        } else {
          flushBigram();
        }
        return true;
      } else if (doNext()) {

        // case 2: look at the token type. should we form any n-grams?
        
        String type = typeAtt.type();
           //判断字符属性,是否是CJK字符
        if (type == doHan || type == doHiragana || type == doKatakana || type == doHangul) {
          
          // acceptable CJK type: we form n-grams from these.
          // as long as the offsets are aligned, we just add these to our current buffer.
          // otherwise, we clear the buffer and start over.
          
          if (offsetAtt.startOffset() != lastEndOffset) { // unaligned, clear queue
            if (hasBufferedUnigram()) {
              
              // we have a buffered unigram, and we peeked ahead to see if we could form
              // a bigram, but we can't, because the offsets are unaligned. capture the state 
              // of this peeked data to be revisited next time thru the loop, and dump our unigram.
              
              loneState = captureState();
              flushUnigram();
              return true;
            }
            index = 0;
            bufferLen = 0;
          }
          refill();
        } else {
          
          // not a CJK type: we just return these as-is.
          
          if (hasBufferedUnigram()) {
            
            // we have a buffered unigram, and we peeked ahead to see if we could form
            // a bigram, but we can't, because its not a CJK type. capture the state 
            // of this peeked data to be revisited next time thru the loop, and dump our unigram.
            
            loneState = captureState();
            flushUnigram();
            return true;
          }
          return true;
        }
      } else {
        
        // case 3: we have only zero or 1 codepoints buffered, 
        // so not enough to form a bigram. But, we also have no
        // more input. So if we have a buffered codepoint, emit
        // a unigram, otherwise, its end of stream.
        
        if (hasBufferedUnigram()) {
          flushUnigram(); // flush our remaining unigram
          return true;
        }
        return false;
      }
    }
  }




相关文章:

  • 如何建立基于CocoaPods的ReactiveCocoa工程
  • Webservice-XML与Java(五)
  • Java中SimpleDateFormat用法详解
  • Parcelable protocol requires a Parcelable.Creator object called。。。。。
  • MOTOROLA MC40 android系统扫描开发
  • cocos2d-x开启IOS多点触控
  • android友盟注意事项
  • Android编程之Intent源码详解
  • Android编程之LocalBroadcastManager源码详解
  • Android编程之DialogFragment源码详解(一)
  • Android编程之DialogFragment源码详解(二)
  • 在Mac上配置cocos2d-x 3.0,xcode5资源无法刷新的问题
  • 在Mac上配置cocos2d-x 3.0的Android开发环境
  • cocos2d-x 3.0的lua-binding接口导出
  • Sublime Text 3技巧:支持GB2312和GBK编码
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • ES6系统学习----从Apollo Client看解构赋值
  • Git学习与使用心得(1)—— 初始化
  • js对象的深浅拷贝
  • python3 使用 asyncio 代替线程
  • Python连接Oracle
  • Sublime Text 2/3 绑定Eclipse快捷键
  • 动态规划入门(以爬楼梯为例)
  • 好的网址,关于.net 4.0 ,vs 2010
  • 前端性能优化--懒加载和预加载
  • 设计模式 开闭原则
  • 译米田引理
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • (1)虚拟机的安装与使用,linux系统安装
  • (4.10~4.16)
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转)负载均衡,回话保持,cookie
  • (转)用.Net的File控件上传文件的解决方案
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • .Net 6.0 处理跨域的方式
  • .net 后台导出excel ,word
  • .net 简单实现MD5
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • /deep/和 >>>以及 ::v-deep 三者的区别
  • @GetMapping和@RequestMapping的区别
  • @Validated和@Valid校验参数区别
  • @德人合科技——天锐绿盾 | 图纸加密软件有哪些功能呢?
  • [ 蓝桥杯Web真题 ]-Markdown 文档解析
  • [bzoj1038][ZJOI2008]瞭望塔
  • [IE技巧] IE8中HTTP连接数目的变化
  • [java/jdbc]插入数据时获取自增长主键的值