lucene 7.x 分词 TokenStream的使用及源码分析

lucene 7.x 分词 TokenStream的使用及源码分析一.使用步骤1//将一个字符串创建成token流,第一个参数fiedName,是一种标志性参数,可以写空字符串,不建议用null,因为null对于IKAnalyzer会包错2TokenStr

大家好,又见面了,我是你们的朋友全栈君。

一.使用步骤

 1 //将一个字符串创建成token流,第一个参数---fiedName,是一种标志性参数,可以写空字符串,不建议用null,因为null对于IKAnalyzer会包错
 2         TokenStream tokenStream = new IKAnalyzer().tokenStream("keywords",new StringReader("思想者"));  3         //添加单词信息到AttributeSource的map中
 4         CharTermAttribute attribute = tokenStream.addAttribute(CharTermAttribute.class);  5         //重置,设置tokenstream的初始信息
 6  tokenStream.reset();  7         while(tokenStream.incrementToken()) {//判断是否还有下一个Token
 8  System.out.println(attribute);  9  } 10  tokenStream.end(); 11         tokenStream.close();

 

二.代码与原理分析

TokenStream用于访问token(词汇,单词,最小的索引单位),可以看做token的迭代器

1.如何获得TokenStream流 —->对应第一行代码

先获得TokenStreamComponents,从他获得TokenStream(TokenStreamComponents内部封装了一个TokenStream以及一个Tokenizer,关于Tokenizer下面会具体讲)

<span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

可以看到主要是通过reuseStrategy对象获得TokenStreamComponents,然后通过components对象获得所需的TokenStream流.reuseStrategy对象即为”复用策略对象”,但是如何获得此对象?

通过下面这两张图可以看到在Analyzer的构造器中通过传入GLOBAL_REUSE_STRATEGY对象完成了reuseStrategy对象的初始化.

ReuseStrategy是Analyzer的一个静态内部类,同时他也是一个抽象类,其子类也是Analyzer的内部类,上面提到了GLOBAL_REUSE_STRATEGY,这个对象是通过匿名类的方式继承了ReuseStrategy获得

的(第三张图)

<span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

<span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

<span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

当然你会说Analyzer不是抽象类吗?他的构造器怎么被调用?因为我们用到的各种分词器,如IKAnalyzer,StandAnalyzer都是Analyzer的子类或间接子类,new一个分词器对象时会调用父类分词器的构造器

接下来就是 reuseStrategy.getReusableComponents(this, fieldName);通过上面的分析,发现调用的getReusableComponents方法就是调用GLOBAL_REUSE_STRATEGY对象里的getReusableComponents

这个方法又把我们传入的分词器对象传递给ReuseStrategy类里的getStoredValue方法,最后通过storedValue(老版本里叫做tokenStreams)获得TokenStreamComponents对象(储存在ThreadLocal中)

可以看到查找的时候根本没用到fieldname,这也是为什么说new xxxAnalyzer().tokenStream()时第一个参数filedname可以写空字符串的原因

 <span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

<span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

关于CloseableThreadLocal做个简略的说明:

CloseableThreadLocal是lucene对java自带的的ThreadLocal的优化,解决了jdk中定期执行无效对象回收的问题

请参考:https://www.cnblogs.com/jcli/p/talk_about_threadlocal.html

 既然获得了TokenStreamComponents对象,接下来初始化Reader对象,事实上这个初始化就是把你传入的reader对象返回过来,

<span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

 <span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

接着往下走判断components对象是否为空?为null则新创建一个components对象,Analyezer的createComponents是个抽象方法,我们以其子类IKAnalyzer中的此方法作为解析

<span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

这里又出现了一个新的类Tokenizer,Tokenizer说白了也是一个TokenStream,但是其input是一个Reader,这意味着Tokenizer是对字符操作,换句话说由Tokenizer来进行分词,即生成token

TokenStream还有一个重要的子类叫做TokenFilter,其input是TokenStream,也就是说他负责对token进行过滤,如去除标点,大小写转换等,从上面贴的IKAnalyzer的createComponents方法看不到TokenFilter的影子

贴下标准分词器里的代码

<span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

到这TokenStreamComponents对象创建完成了,大体的流程是先检查复用策略对象里有没有现成的components对象可用,有的话直接拿过来用,没有的话再去创建,创建完成

后加入复用策略对象里,以便下次使用.获得了TokenStreamComponents就可以获得TokenStream对象

组合不同的Tokenizer和TkoenFilter就变成了不同的Analyzer

 

2.AttributeImpl与AttributeSource  ——–>对应第二行代码

AttributeImpl是Attribute接口的实现类,简单的说AttributeImpl用来存储token的属性,主要包括token的文本,位置,偏移量.位置增量等信息,比如CharTermAttribute保存文本

OffsetAttribute保存偏移量,PositionIncrementAttribute用于保存位置增量,而AttributeSource又包含了一系列的AttributeImpl,换句话说AttributeSource是token的属性集合,

AttributeSource内部有两个map.分别定义了从xxxAttribute—->AttributeImpl,xxxAttributeImpl—–>AttributeImpl两种映射关系,这样保证了xxxAttributeImpl对于同一个AttributeSource只有一个实例

<span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

 所以需要什么信息,就用tokenStream.addAttribute(xxx.Class)即可

//添加单词信息到AttributeSource的两个map中
CharTermAttribute attribute = tokenStream.addAttribute(CharTermAttribute.class);

 

3.reset

lucene各个版本的API变化很大,网上好多的资料都有些过时了,比如 TokenStream contract violation: reset()/close() call missing这个异常是

因为在调用incrementToken()方法前没有调用reset()方法,一些老版本不需要调用,然而现在高版本的lucene必须先调用reset()把used属性设置为

false后才能执行incrementToken()

<span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

 

<span role="heading" aria-level="2">lucene 7.x 分词 TokenStream的使用及源码分析

重置的目的是为了让告诉incrementToken(),此流未被使用过,要从流的开始处返回词汇

 

4.incrementToken()

是否还有下一个词汇

5.end()与close()

end()调用endAttribute(),把termlength设置为0,意思是没有词汇了为close()做准备

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/154984.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • cuda_error_out_of_memory(out of memory怎么办)

    报错如下思路简洁明了,他已经告诉你了,默认使用的那gpu内存不足。在操作系统输入如下,查一下memory现在的状态:nvidia-smi害,发现GPU-0有一个进程正在执行导致1GB剩余都不够。我们用GPU-1执行就行啦!问题解决python文件中:importosos.environ[“CUDA_VISIBLE_DEVICES”]=’1’解决了。…

    2022年4月10日
    433
  • Http通过header传递参数_http contenttype

    Http通过header传递参数_http contenttype提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、header常用指令header分为三部分:发送一个200正常响应set404header:页面没找到页面被永久删除,可以告诉搜索引擎更新它们的urls访问受限服务器错误重定向到一个新的位置延迟一段时间后重定向覆盖X-Powered-Byvalue内容语言(en=English)最后修改时间(在缓存的时候可以用到)告诉浏览器要获取的内容还没有更新设置内容的长度(缓存的时候可以用到):用来下载文件:禁止

    2022年8月24日
    7
  • Pytest(11)allure报告[通俗易懂]

    Pytest(11)allure报告[通俗易懂]前言allure是一个report框架,支持java的Junit/testng等框架,当然也可以支持python的pytest框架,也可以集成到Jenkins上展示高大上的报告界面。mac环境:

    2022年7月31日
    6
  • VRRP(超详细)

    VRRP(超详细)12VRRP12 1 为什么要有 vrrp 主要为了防止单点故障既有网关冗余 当网关发生故障的时候 能让 PC 快速的切换 12 2VRRP 的概念通过 VRRP 将俩台路由器虚拟构成一台路由器 俩台路由器的浮动地址 即是路由器的虚拟地址 浮动地址也是下行地址的网关 IP 通俗的讲 VRRP 实现了一个组中的路由器 哪个路由器工作 哪个路由器作为备份 实际上 如果一个组中有俩个路由 其可以理解为三个路由

    2025年6月23日
    2
  • vue父组件引入子组件_vue子组件传递方法给父组件

    vue父组件引入子组件_vue子组件传递方法给父组件子组件代码<template> <divclass=”item”@click=”gotoView($event)”> <divclass=”iconfont-box”> <slot></slot> </div> <divclass=”title”>Blog</div> </div></template><script>export

    2022年9月26日
    3
  • bat命令大全_bat暂停命令

    bat命令大全_bat暂停命令文章目录一、bat(批处理文件类型)注意事项命令简介二、使用步骤1.引入库2.读入数据总结一、bat(批处理文件类型)注意事项1.文件保存格式为ANSI2.以管理员身份运行文件命令简介cmd #相当于已管理员身份执行了命令提示符@echo(off|on) #关闭或打开回显命令@echooffipconfigpause #相当于自动打开cmd(命令提示符)输入ipconfig查看电脑网络信息cd/d路径地址 #Windows下进入指定路径pause #一般在

    2022年9月24日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号