zoukankan      html  css  js  c++  java
  • String,StringBuilder和StringBuffer的特点和使用场景

    这三个类是平时开发中经常遇到的,主要差别是运行速度和线程安全,使用起来String最方便了,另外两个稍微复杂一些。

    从运行速度角度看,StringBuilder>StringBuffer>String。

    从线程安全角度看,StringBuffer是线程安全的,StringBuilder和String不是。

    下面从代码的角度分析一下,示例代码:

     1             StringBuilder strBuilder = new StringBuilder();
     2             strBuilder.append(100);
     3             strBuilder.append("123");
     4 
     5             StringBuffer strBuffer = new StringBuffer();
     6             strBuffer.append(100);
     7             strBuffer.append("123");
     8             
     9             String strTest = "start";
    10             strTest += 100;
    11             strTest += "123";

    首选看下StringBuilder的实现:

     1     public StringBuilder append(int i) {
     2         super.append(i);
     3         return this;
     4     }
     5 
     6 public AbstractStringBuilder append(int i) {
     7         if (i == Integer.MIN_VALUE) { // 是否是最小值
     8             append("-2147483648");
     9             return this;
    10         }
    11        // 计算i的字符串长度,判断是否需要增大存储空间
    12         int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1
    13                                      : Integer.stringSize(i);
    14         int spaceNeeded = count + appendedLength;
    15         ensureCapacityInternal(spaceNeeded);
    16         Integer.getChars(i, spaceNeeded, value);  // 使用Integer的getChars方法,计算i的字符串值并把值拷贝到value中
    17         count = spaceNeeded;
    18         return this;
    19     }
    // 其中扩展空间时,会按照现有空间的2倍+2来扩展,保证不需要一直来扩展,提高效率
    void expandCapacity(int minimumCapacity) {
    int newCapacity = value.length * 2 + 2;
    if (newCapacity - minimumCapacity < 0)
    newCapacity = minimumCapacity;
    if (newCapacity < 0) {
    if (minimumCapacity < 0) // overflow
    throw new OutOfMemoryError();
    newCapacity = Integer.MAX_VALUE;
    }
    // 计算好扩展大小后,重新申请存储空间并把旧值拷贝到新的存储空间
    value = Arrays.copyOf(value, newCapacity);
    }
    //Arrays.copyOf的实现
    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;
    }
     1     public StringBuilder append(String str) {
     2         super.append(str);
     3         return this;
     4     }
     5 public AbstractStringBuilder append(String str) {
     6         if (str == null) str = "null";
     7         int len = str.length();
     8         ensureCapacityInternal(count + len);
     9         str.getChars(0, len, value, count);  // 使用了String的getChars方法把str拷贝到value中去
    10         count += len;
    11         return this;
    12     }
    13 
    14 str.getChars代码:
    15 public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
    16         if (srcBegin < 0) {
    17             throw new StringIndexOutOfBoundsException(srcBegin);
    18         }
    19         if (srcEnd > value.length) {
    20             throw new StringIndexOutOfBoundsException(srcEnd);
    21         }
    22         if (srcBegin > srcEnd) {
    23             throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
    24         }
    25         // 最终使用 System.arraycopy完成字符串的拷贝
    26         System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    27     }

    再看下StringBuffer的实现:

    1     public synchronized StringBuffer append(int i) { // 多了同步关键字,是线程安全的
    2         super.append(i);  // 调用了AbstractStringBuilder的append方法,和StringBuilder使用的是一样的方法
    3         return this;
    4     }
    1     public synchronized StringBuffer append(String str) { // 使用了同步关键字
    2         super.append(str);  // 使用了AbstractStringBuilder的方法
    3         return this;
    4     }

    从上面分析可以看到,StringBuffer和StringBuilder是继承了相同的父类AbstractStringBuilder,然后通过在方法上使用了同步关键字实现了线程安全,看下类定义:

    1 public final class StringBuilder
    2     extends AbstractStringBuilder
    3     implements java.io.Serializable, CharSequence
    4 {}
    5 
    6 public final class StringBuffer
    7     extends AbstractStringBuilder
    8     implements java.io.Serializable, CharSequence
    9 {}

    最后再看下String的操作,jvm会申请一段新的char数组,并把"start"和"100"顺序拷贝进去,第二次再申请一段新的char数组,并把"start100"和"123"顺序拷贝进去。

    由于String的每次拷贝都会有申请新的存储空间和拷贝动作,而StringBuffer和StringBuilder只有在空间不够用的时候才会申请新的存储空间,因此从效率上讲String是最慢的。

    综上所述,对String,StringBuilder和StringBuffer的使用做个小结:

    1. String 适用次数较少的拷贝场景。

    2. StringBuilder用无线程安全要求的大量拷贝场景。

    2. StringBuffer用要求线程安全的大量拷贝场景。

  • 相关阅读:
    线程池
    多线程随笔
    注解随笔
    反射机制
    iO流
    FastDFS+docker建立分布式文件系统
    Java之Exception
    Java之String
    手写SpringMvc
    spring中一些常用注解的含义
  • 原文地址:https://www.cnblogs.com/xinghebuluo/p/8557739.html
Copyright © 2011-2022 走看看