1.概述
在Lucene中,有很多地方都会用的基本类型数组,如ByteBlockPool中的二维数byte数组buffers,其中的每一个元素buffer(block)就是一个一维的byte[]。如果我们需要获得block中的某一区间(一般是连续的),则需要数组的拷贝,效率十分低,要在索引过程中需要频繁的读取。BytesRef的出现极大缓解这一问题,它内部可以持有某一个block的引用,通过offset和length来指明截取的位置和长度,过程中不需要频繁的拷贝。但有时候我们读取可能会跨block读取,涉及两个数组,还是需要将目标数据拷贝生成新数组,然后被BytesRef引用。BytesRef内部还提供了对其表示的字节数组进行转码的操作。
2.属性
//空数组
public static final byte[] EMPTY_BYTES = new byte[0];
//大多情况下是一个buffer的引用,当需要表示跨buffer数据时,则引用一个手动生成的数组
public byte[] bytes;
//偏移量
public int offset;
//长度
public int length;
3.构造方法
//无参构造
public BytesRef() {
this(EMPTY_BYTES);
}
//引用整个byte[]
public BytesRef(byte[] bytes) {
this(bytes, 0, bytes.length);
}
//引用截取部分
public BytesRef(byte[] bytes, int offset, int length) {
this.bytes = bytes;
this.offset = offset;
this.length = length;
assert isValid();
}
//引用一个指定容量的数组
public BytesRef(int capacity) {
this.bytes = new byte[capacity];
}
//将将字符串转进行UTF-8编码成字节数组,然后引用
public BytesRef(CharSequence text) {
//保证容量足够
this(new byte[UnicodeUtil.maxUTF8Length(text.length())]);
//引用有效部分
length = UnicodeUtil.UTF16toUTF8(text, 0, text.length(), bytes);
}
4.主要方法
4.1 utf8ToString()
将对象引用的字节数组视为UTF-8编码,转码为字符串(UTF-16)
public String utf8ToString() {
//保证字符容量足够(字节数)
final char[] ref = new char[length];
//指定byet数组的指定区间UTF-8转码成UTF-16(jvm内部字符串是utf16),返回字符数
final int len = UnicodeUtil.UTF8toUTF16(bytes, offset, length, ref);
return new String(ref, 0, len);
}
JVM内部对字符串使用UTF-16编码,好处是大部分情况Unicode码而二进制就是其编码结果。
UnicdoeUtil封装了许多编解码、转码的方法,有兴趣可以看看。
4.2 deepCopyOf(BytesRef other)
这是一个静态方法,对指定BytesRef进行深拷贝(数组复制),返回拷贝得到的BytesRef。
public static BytesRef deepCopyOf(BytesRef other) {
return new BytesRef(ArrayUtil.copyOfSubArray(other.bytes, other.offset, other.offset + other.length), 0, other.length);
}
4.3 clone()
BytesRef实现了Cloneable接口,重写了clone方法,实现了浅拷贝
public BytesRef clone() {
return new BytesRef(bytes, offset, length);
}
4.4 bytesEquals(BytesRef other)
判断与指定的ByteRef所表示的内容是否完全相等
public boolean bytesEquals(BytesRef other) {
//两个数组在指定范围是否相等,左闭右开
return FutureArrays.equals(this.bytes, this.offset, this.offset + this.length,
other.bytes, other.offset, other.offset + other.length);
}
4.5 其他方法
- 其实现了Comparable接口,重写了compareTo方法,逐个byte比较,升序。如果所有byte相等,则长度(字节数)升序。
- equals方法比较原则:字节长度相等且每个byte相等为true。
- isValid方法进行属性验证,抛出IllegalStateException异常或返回true。