LUCENE-4315: Add ReusableStringReader to Field.java

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1376261 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Uwe Schindler 2012-08-22 21:29:36 +00:00
parent 568156b710
commit 518fc20d1c
3 changed files with 92 additions and 5 deletions

View File

@ -104,8 +104,8 @@ Bug Fixes
Optimizations
* LUCENE-4317: Improve reuse of internal TokenStreams in oal.document.Field.
(Uwe Schindler, Chris Male, Robert Muir)
* LUCENE-4317: Improve reuse of internal TokenStreams and StringReader
in oal.document.Field. (Uwe Schindler, Chris Male, Robert Muir)
Build

View File

@ -19,7 +19,6 @@ package org.apache.lucene.document;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.NumericTokenStream;
@ -73,7 +72,8 @@ public class Field implements IndexableField {
// customize how it's tokenized:
protected TokenStream tokenStream;
protected transient TokenStream internalTokenStream;
private transient TokenStream internalTokenStream;
private transient ReusableStringReader internalReader;
protected float boost = 1.0f;
@ -460,12 +460,56 @@ public class Field implements IndexableField {
} else if (readerValue() != null) {
return analyzer.tokenStream(name(), readerValue());
} else if (stringValue() != null) {
return analyzer.tokenStream(name(), new StringReader(stringValue()));
if (internalReader == null) {
internalReader = new ReusableStringReader();
}
internalReader.setValue(stringValue());
return analyzer.tokenStream(name(), internalReader);
}
throw new IllegalArgumentException("Field must have either TokenStream, String, Reader or Number value");
}
static final class ReusableStringReader extends Reader {
private int pos = 0, size = 0;
private String s = null;
void setValue(String s) {
this.s = s;
this.size = s.length();
this.pos = 0;
}
@Override
public int read() {
if (pos < size) {
return s.charAt(pos++);
} else {
s = null;
return -1;
}
}
@Override
public int read(char[] c, int off, int len) {
if (pos < size) {
len = Math.min(len, size-pos);
s.getChars(pos, pos+len, c, off);
pos += len;
return len;
} else {
s = null;
return -1;
}
}
@Override
public void close() {
pos = size; // this prevents NPE when reading after close!
s = null;
}
}
static final class StringTokenStream extends TokenStream {
private final CharTermAttribute termAttribute = addAttribute(CharTermAttribute.class);
private final OffsetAttribute offsetAttribute = addAttribute(OffsetAttribute.class);
@ -506,6 +550,11 @@ public class Field implements IndexableField {
public void reset() {
used = false;
}
@Override
public void close() {
value = null;
}
}
/** Specifies whether and how a field should be stored. */

View File

@ -18,9 +18,11 @@ package org.apache.lucene.document;
*/
import java.io.StringReader;
import java.nio.CharBuffer;
import org.apache.lucene.analysis.CannedTokenStream;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.document.Field.ReusableStringReader;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.LuceneTestCase;
@ -610,4 +612,40 @@ public class TestField extends LuceneTestCase {
// expected
}
}
public void testReusableStringReader() throws Exception {
ReusableStringReader reader = new ReusableStringReader();
assertEquals(-1, reader.read());
assertEquals(-1, reader.read(new char[1]));
assertEquals(-1, reader.read(new char[2], 1, 1));
assertEquals(-1, reader.read(CharBuffer.wrap(new char[2])));
reader.setValue("foobar");
char[] buf = new char[4];
assertEquals(4, reader.read(buf));
assertEquals("foob", new String(buf));
assertEquals(2, reader.read(buf));
assertEquals("ar", new String(buf, 0, 2));
assertEquals(-1, reader.read(buf));
reader.close();
reader.setValue("foobar");
assertEquals(0, reader.read(buf, 1, 0));
assertEquals(3, reader.read(buf, 1, 3));
assertEquals("foo", new String(buf, 1, 3));
assertEquals(2, reader.read(CharBuffer.wrap(buf, 2, 2)));
assertEquals("ba", new String(buf, 2, 2));
assertEquals('r', (char) reader.read());
assertEquals(-1, reader.read(buf));
reader.close();
reader.setValue("foobar");
StringBuilder sb = new StringBuilder();
int ch;
while ((ch = reader.read()) != -1) {
sb.append((char) ch);
}
reader.close();
assertEquals("foobar", sb.toString());
}
}