【问题标题】:The process which Lucene tokenizes textLucene 标记文本的过程
【发布时间】:2011-01-13 20:33:54
【问题描述】:

这可以被视为一般 Java 问题,但为了更好地理解,我使用 Lucene 作为示例。

您可以在 Lucene 中使用不同的标记器来标记文本。有主要的抽象 Tokenizer 类,然后是许多不同的扩展它的类。 TokenFilter 也是一样。

现在,似乎每次您想要索引文档时,都会创建一个新的 Tokenizer。问题是,既然 Tokeinzer 只是一个实用程序类,为什么不让它成为静态的呢?例如,将所有字母转换为小写的 Tokenizer 可以有一个静态方法,该方法对它获得的每个输入都执行此操作。为我们要索引的每段文本创建一个新对象有什么意义?

有一点需要提一下——Tokeinzer 有一个私有字段,其中包含它接收到的用于标记化的输入。我只是不明白为什么我们需要以这种方式存储它,因为对象在标记化过程结束后立即被销毁并返回新的标记化文本。我唯一能想到的可能是多线程访问?

谢谢!

【问题讨论】:

    标签: lucene static-classes


    【解决方案1】:

    现在,似乎每次你想要索引一个文档时,都会创建一个新的 Tokenizer

    这不是真的,调用了 Analyzer.reusableTokenStream 方法,它重用了 不仅仅是一个 Tokenizer,还有整个链(TokenFilters 等)。 见http://lucene.apache.org/java/3_0_0/api/core/org/apache/lucene/analysis/Analyzer.html#reusableTokenStream(java.lang.String,java.io.Reader)

    有一点需要提一下——Tokeinzer 有一个私有字段,其中包含它接收到的用于标记化的输入。我只是不明白为什么我们需要以这种方式存储它,因为对象在标记化过程结束后立即被销毁并返回新的标记化文本。我唯一能想到的可能是多线程访问?

    如前所述,整个分词器和分词过滤器链可跨文档重用。所以它们的所有属性都被重用了,但重要的是要注意属性是跨链共享的(例如,所有 Tokenizer 和 TokenFilters 的 Attribute 引用都指向相同的实例)。这就是为什么在标记器中调用 clearAttributes() 来重置所有属性至关重要的原因。

    例如,Whitespace 标记器在其 ctor 中添加对 TermAttribute 的引用,并由 LowerCaseFilter 包装,后者也在其 ctor 中添加对 TermAttribute 的引用。这两个 TermAttributes 都指向相同的底层 char[]。当一个新文档被处理时,Analyzer.reusableTokenStream 被调用,它返回之前文档中使用的相同的 TokenStream 链(在这种情况下,Whitespace 用 LowerCaseFilter 包装)。调用 reset(Reader) 方法,将分词器的输入重置为新的文档内容。最后在整个流上调用reset(),这会重置之前文档的任何内部状态,并处理内容直到incrementToken() 返回false。

    【讨论】:

    • 非常感谢。现在这很有意义。
    【解决方案2】:

    在执行复杂的操作(例如使用 Lucene 索引文档)时,不必担心在这里和那里创建类的实例。在标记化和索引过程中可能会创建很多很多对象。当进程完成时比较丢弃的对象的剩余垃圾时,再添加一个标记器实例实际上什么都不是。如果您不相信我,请获取配置文件并查看对象创建计数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-23
      • 1970-01-01
      • 1970-01-01
      • 2014-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多