3

これは一般的なJavaの質問と見なすことができますが、理解を深めるために、例としてLuceneを使用しています。

Luceneでさまざまなトークナイザーを使用して、テキストをトークン化できます。メインの抽象Tokenizerクラスと、それを拡張するさまざまなクラスがあります。TokenFilterについても同じです。

これで、ドキュメントのインデックスを作成するたびに、新しいTokenizerが作成されるようです。問題は、Tokeinzerは単なるユーティリティクラスなので、静的にしてみませんか?たとえば、すべての文字を小文字に変換するTokenizerは、取得するすべての入力に対してそれを実行する静的メソッドを持つことができます。インデックスを作成するすべてのテキストに対して新しいオブジェクトを作成することのポイントは何ですか?

言及すべきことの1つ-Tokeinzerには、トークン化するために受け取る入力を含むプライベートフィールドがあります。トークン化プロセスが終了した直後にオブジェクトが破棄され、新しいトークン化されたテキストが返されるため、この方法で保存する必要がある理由がわかりません。私が考えることができる唯一のことは、多分マルチスレッドアクセスですか?

ありがとうございました!

4

2 に答える 2

6

現在、ドキュメントのインデックスを作成するたびに、新しいトークナイザーが作成されているようです

これは正しくありません。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)を参照してください。

言及すべきことの 1 つ - Tokeinzer には、トークン化するために受け取る入力を含むプライベート フィールドがあります。トークン化プロセスが終了し、新しいトークン化されたテキストが返された直後にオブジェクトが破棄されるため、この方法で保存する必要がある理由がわかりません。私が考えることができる唯一のことは、おそらくマルチスレッドアクセスですか?

前述のように、トークナイザーとトークンフィルターのチェーン全体がドキュメント間で再利用されます。そのため、すべての属性が再利用されますが、チェーン全体で属性が共有されることに注意することも重要です (たとえば、すべてのトークナイザーと TokenFilter の属性参照は同じインスタンスを指します)。これが、トークナイザーで clearAttributes() を呼び出してすべての属性をリセットすることが重要な理由です。

例として、ホワイトスペース トークナイザーはその ctor に TermAttribute への参照を追加し、その ctor にも TermAttribute への参照を追加する LowerCaseFilter によってラップされます。これらの TermAttributes は両方とも、基になる同じ char[] を指しています。新しいドキュメントが処理されると、Analyzer.reusableTokenStream が呼び出され、前のドキュメントで使用されたのと同じ TokenStream チェーン (この場合は、LowerCaseFilter でラップされた空白) が返されます。reset(Reader) メソッドが呼び出され、トークナイザーの入力が新しいドキュメントの内容にリセットされます。最後に、ストリーム全体で reset() が呼び出され、前のドキュメントの内部状態がリセットされ、incrementToken() が false を返すまでコンテンツが処理されます。

于 2011-01-14T11:43:52.517 に答える
0

Lucene を使用してドキュメントのインデックスを作成するような複雑なことを行うときに、クラスのあちこちにインスタンスを作成することを心配する必要はありません。トークン化とインデックス作成のプロセス内で、おそらく非常に多くのオブジェクトが作成されるでしょう。プロセスが完了したときに、捨てられたオブジェクトから残ったガベージを比較すると、もう 1 つのトークナイザー インスタンスは文字通り何もありません。信じられないなら、プロファイルを取得してオブジェクトの作成数を監視してください。

于 2011-01-14T11:53:01.303 に答える