First, the efficiency of the connection string
Why use String slow connection string?
Little knowledge
After java in the array is initialized, the memory space occupied by the array length of the array is immutable.
Create a string, to allocate memory space for the string object will be consumed a certain amount of time (CPU) and space (memory) as the cost of the most basic data types, a large number of frequently create a string, to a great extent influence the program performance.
Excessive useless intermediate object
Each time the connection string will create a new String object, with the increase in the number of stitching, this object will keep rising. For example, 100 times splicing need to create a String object 100 to be able to achieve their goals.
Why StringBuilder higher efficiency when connected?
Character array expansion mechanism:
void ensureCapacityInternal Private (int minimumCapacity) { // if the minimum required capacity minimumCapacity array length is longer than the original // overflow-Conscious code IF (minimumCapacity - value.length> 0) { value = Arrays.copyOf (value, newCapacity (minimumCapacity )); } } Private newCapacity int (int be minCapacity) { // computing capacity after expansion newCapacity // overflow-Conscious code int newCapacity = (value.length <<. 1) + 2; also less than the required after expansion // minimum capacity IF (newCapacity - be minCapacity <0) { // set new minimum required capacity is the capacity of the minimumCapacity newCapacity be minCapacity =; } // newCapacity has overflowed, if newCapacity bigger than the maximum capacity that can be allocated MAX_ARRAY_SIZE array. return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity <0) hugeCapacity (minCapacity)? : newCapacity; } Private hugeCapacity int (int minCapacity) { // the minimum required capacity of the memory overflow exception is thrown minCapacity greater than Integer.MAX_VALUE IF ( Integer.MAX_VALUE - minCapacity <0) {// overflow the throw an OutOfMemoryError new new (); } // if minCapacity between MAX_ARRAY_SIZE and Integer.MAX_VALUE, then the new capacity minCapacity, or used directly as a new MAX_ARRAY_SIZE capacity. return (minCapacity> MAX_ARRAY_SIZE) ? minCapacity: MAX_ARRAY_SIZE; }
StringBuilder object when the original string is added:
1. Append additional objects str 'null' is null character
2. Verify whether the need for expansion of operations
2.1 最小所需容量minimumCapacity是否比原数组长度要长,即当原数组长度不能满足所需最小容量时进行扩容操作。
2.2 计算扩容之后的容量newCapacity,newCapacity = (value.length * 2) + 2。
2.3 扩容后是否还小于所需的最小容量,如果小于则直接设置新容量为最小所需容量minimumCapacity。
2.4 newCapacity是否溢出,newCapacity是否比数组所能分配的最大容量 MAX_ARRAY_SIZE 还要大。如果是的话则判断,最小所需容量minCapacity大于Integer.MAX_VALUE时抛出内存溢出异常,如果minCapacity介于MAX_ARRAY_SIZE和Integer.MAX_VALUE之间,则新的容量为minCapacity,否则直接使用MAX_ARRAY_SIZE作为新的容量。
3.str.getChars () will be appended to the end value of str
The reason for the high efficiency
- Expansion mechanism ensures that, only if they meet the conditions expansion will generate a new array capacity expansion, the so most cases are in the original array operations, avoid excessive useless char [] objects, saving system resources overhead.
minimumCapacity - value.length > 0
Code
/ ** * Comparative concatenation speed * * @author: lingyejun * @date: 2019/8/17 * @Describe: * By @Modified: * / public class LinkCompare { / ** * original concatenation * * @ Times param * / public static void linkByString (int Times) { Long the startTime = System.currentTimeMillis (); String initStr = ""; for (int I = 0; I <Times; I ++) { initStr initStr + = I; } Long = System.currentTimeMillis endTime (); System.out.println ( "String connection" + times + "consumption times:" + (endTime - the startTime) + "MS"); } /** * 使用StringBuilder连接字符串 * * @param times */ public static void linkByStringBuilder(int times) { Long startTime = System.currentTimeMillis(); StringBuilder initStr = new StringBuilder(); for (int i = 0; i < times; i++) { initStr.append(i); } Long endTime = System.currentTimeMillis(); System.out.println("StringBuilder 连接 " + times + " 次 消耗:" + (endTime - startTime) + "ms"); } /** * 使用StringBuffer连接字符串 * * @param times */ public static void linkByStringBuffer(int times) { Long startTime = System.currentTimeMillis(); StringBuffer initStr = new StringBuffer(); for (int i = 0; i < times; i++) { initStr.append(i); } Long endTime = System.currentTimeMillis(); System.out.println("StringBuffer 连接 " + times + " 次 消耗:" + (endTime - startTime) + "ms"); } public static void main(String[] args) { // 100000000 linkByStringBuilder(40000); //-XX:+PrintGCDetails //linkByString(40000); } }
Second, the security thread of relatively StringBuilder and String Buffer
Thread safety verification of StringBuffer
Reason not thread-safe
public StringBuilder append(String str) { super.append(str); return this; } public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; }
Test code
import java.util.ArrayList; import java.util.List; /** * StringBuilder和StringBuffer的并发测验 * * @Author: lingyejun * @Date: 2019/8/17 * @Describe: * @Modified By: */ public class SecurityCompare { public void stringBuilderTest() { // 初始化StringBuilder StringBuilder stringBuilder = new StringBuilder(); // joinList List<StringBuilderThread> joinList = new ArrayList<>(); // 模拟并发场景 for (int i = 0; i < 1000; i++) { StringBuilderThread sbt = new StringBuilderThread(stringBuilder); sbt.start(); joinList.add (SBT); } // wait append thread execution is completed before execution of the main thread for (StringBuilderThread Thread: joinlist) { the try { Thread.join (); } the catch (InterruptedException E) { e.printStackTrace (); } } // print the final results System.out.println ( "StringBuilder append concurrent results:" + stringBuilder.length ()); } public void stringBufferTest () { // initialize the stringBuffer the stringBuffer stringBuffer the stringBuffer new new = (); // joinlist List <StringBufferThread> = new new joinlist the ArrayList <> (); // simulate concurrent scenes for (int I = 0; I <1000; I ++) { StringBufferThread SBF = new new StringBufferThread (stringBuffer); sbf.start (); joinList.add (SBF); } // append waiting thread execution is completed before execution of the main thread for (StringBufferThread Thread: joinlist) { the try { Thread.join (); } the catch (InterruptedException E) { e.printStackTrace (); } } // print the final result System.out.println ( "StringBuffer append concurrent results:" stringBuffer.length + ()); } public static void main (String [] args) { SecurityCompare securityCompare new new SecurityCompare = (); securityCompare.stringBuilderTest(); securityCompare.stringBufferTest(); } public static class StringBuilderThread extends Thread { private StringBuilder stringBuilder; public StringBuilderThread(StringBuilder stringBuilder) { this.stringBuilder = stringBuilder; } @Override public void run() { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } stringBuilder.append("a"); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } private static class StringBufferThread extends Thread { private StringBuffer stringBuffer; public StringBufferThread(StringBuffer stringBuffer) { this.stringBuffer = stringBuffer; } @Override public void run() { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } stringBuffer.append("a"); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace (); } } } }
CONCLUSIONS
1.String string of fixed length, StringBuilder StringBuffer and a variable-length string.
2.StringBuffer is thread-safe, StringBuilder is not thread safe.
The default initial capacity 3.StringBuilder and StringBuffer is 16, you can estimate in advance the length of the string of good, to further reduce the overhead caused by expansion.