BytesRef源码阅读(Lucene8.0)

1.概述

Lucene中,有很多地方都会用的基本类型数组,如ByteBlockPool中的二维数byte数组buffers,其中的每一个元素buffer(block)就是一个一维的byte[]。如果我们需要获得block中的某一区间(一般是连续的),则需要数组的拷贝,效率十分低,要在索引过程中需要频繁的读取。BytesRef的出现极大缓解这一问题,它内部可以持有某一个block的引用,通过offsetlength来指明截取的位置和长度,过程中不需要频繁的拷贝。但有时候我们读取可能会跨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
发布了28 篇原创文章 · 获赞 11 · 访问量 1536

猜你喜欢

转载自blog.csdn.net/weixin_42881755/article/details/100114191