【JAVA每日分享-7】面试题:StringBuilder实现原理?

885 阅读3分钟

最近群里的小伙伴分享了面试题,我会每天分享一道。
没有点赞、没有评论、没有关爱 ,我都没有写文章的动力了。

开整—— jdk8,idea

看下StringBuilder类的所有方法(alt+7 / ctrl+f12)

看起来也没啥复杂的,常用的无非是 构造、追加、删除、插入、获取下标、反转。

  1. 构造方法:分为三种,无参构造初始容量16,固定容量,字符长度+16容量
  public StringBuilder() {
        super(16);
  }
 public StringBuilder(int capacity) {
        super(capacity);
  }
 public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
  }
  1. append方法:

大致分为两步,先这样。。。然后那样。。。懂了吧,咳咳 缓解下气氛。

  1. 判断是否需要扩容(newCapacity = 原长度*2+2) 2)将追加字符串拷贝到char[]中
 public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        // 判断容量是否足够,是否需要扩容
        ensureCapacityInternal(count + len);
        // 将字符从字符串复制到目标字符数组。
        str.getChars(0, len, value, count);
        count += len;
        return this;
  }
 private void ensureCapacityInternal(int minimumCapacity) {
        // 新字符串长度大于原字符串长度
        if (minimumCapacity - value.length > 0)
            expandCapacity(minimumCapacity);
 }
 // 扩容方法
 void expandCapacity(int minimumCapacity) {
        // 新容量 = 原长度 * 2 + 2
        int newCapacity = value.length * 2 + 2;
        // 看新字符串长度是否比默认扩容值还大
        if (newCapacity - minimumCapacity < 0)
            // 新容量=新字符串长度
            newCapacity = minimumCapacity;
        // 判断扩容值是否越界
        if (newCapacity < 0) {
            // 判断新字符串长度是否越界
            if (minimumCapacity < 0) 
                throw new OutOfMemoryError();
            newCapacity = Integer.MAX_VALUE;
        }
        value = Arrays.copyOf(value, newCapacity);
  }
  // 将原字符串拷贝到新容量的char数组
  public static char[] copyOf(char[] original, int newLength) {
        char[] copy = new char[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
  }
    // params: 0, 追加字符串长度,扩容后的数组,原字符串长度
    public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        // 追加字符串长度 > 扩容后数组长度
        if (srcEnd > value.length) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        // 0 > 追加字符串长度
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        // 将指定数组拷贝到新数组
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }
  1. delete方法
    public AbstractStringBuilder delete(int start, int end) {
        if (start < 0)
            throw new StringIndexOutOfBoundsException(start);
        if (end > count)
            end = count;
        if (start > end)
            throw new StringIndexOutOfBoundsException();
        int len = end - start;
        if (len > 0) {
            System.arraycopy(value, start+len, value, start, count-end);
            count -= len;
        }
        return this;
    }

  // 删除制定坐标和之前的数据()
  public AbstractStringBuilder deleteCharAt(int index) {
        if ((index < 0) || (index >= count))
            throw new StringIndexOutOfBoundsException(index);
        System.arraycopy(value, index+1, value, index, count-index-1);
        count--;
        return this;
    }

你瞅啥?这还需要啥解释吗?不就是调用 System.arraycopy()嘛

  1. replace方法,都是熟悉的方法就不做赘述了。
    public AbstractStringBuilder replace(int start, int end, String str) {
        if (start < 0)
            throw new StringIndexOutOfBoundsException(start);
        if (start > count)
            throw new StringIndexOutOfBoundsException("start > length()");
        if (start > end)
            throw new StringIndexOutOfBoundsException("start > end");

        if (end > count)
            end = count;
        int len = str.length();
        int newCount = count + len - (end - start);
        ensureCapacityInternal(newCount);
        System.arraycopy(value, end, value, start + len, count - end);
        str.getChars(value, start);
        count = newCount;
        return this;
    }

StringBuilder底层就是维护一个char[ ],调用System.arraycopy() 方法构建一个新的char[ ]


Fighting~ 最近在看Spring讲解,对Spring框架有了更深的了解,推荐大家看一看。想要成为架构师怎么能停留在会用的角度去看待技术呢。