StringBuffer进行字符串拼接

在实际开发中,如果需要进行字符串的频繁拼接,会有什么问题?

  • 因为Java中的字符串是不可变的。每一次拼接都会产生新的 字符串。这样会占用大量的方法区内存,造成内存空间的浪费。

    String str = "Hello" + "World";
    

    以上代码就创建了三个String对象在方法区当中。HelloWorldHelloWorld

  • 使用StringBuffer

    StringBuffer stringBuffer = new StringBuffer();
    
  • 字符串拼接,调用append方法

    stringBuffer.append("Hello");
    stringBuffer.append("World");
    
  • String底层使用的是final修饰的byte[]数组存储字符串,而在StringBuffer底层,也是使用byte[],区别是它并没有使用final修饰。byte[]默认长度是16,在append方法中,如果追加的时候byte[]满了,会自动扩容

    底层代码

    public synchronized StringBuffer append(String str) {
      toStringCache = null;
      super.append(str);
      return this;
    }
    
    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;
    }
    

    检查byte[]是否需要扩容

    private void ensureCapacityInternal(int minimumCapacity) {
      // overflow-conscious code
      if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                              newCapacity(minimumCapacity));
      }
    }
    

    对数组进行扩容 System.arraycopy

    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;
    }
    
  • 如何优化StringBuffer的性能?

    1. 在创建StringBuffer的时候尽可能给定一个初始化容量。减少底层数组的扩容次数。
  • StringBufferStringBuilder区别

    • StringBuffer中的方法都有synchronized关键字修饰,表示Stringbuffer在多线程环境下运行是安全的。
    • StringBuilder中的方法都没有synchronized关键字修饰,表示StringBuffer在多线程环境下是不安全的。

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×