String字符串
1、字符串创建过程
String s1 = "abc";
String s2 = new String("abc");
String s3 = s1.intern();
String s4 = s2.intern();
String s5 = s1+"def";
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1 == s4);
s1创建过程:jvm会在之前编译类文件时直接将"abc"的对象引用放到元数据区(常量池),然后在赋值时将s1指向"abc",后面常量池中的操作都是指字符串的对象引用
s2创建过程:在堆中创建一个string对象,然后将该对象指向常量池中的"abc"(问了一下前辈,据说这部分由底层C++库实现)
s3、s4创建过程:返回常量池中"abc"的内存地址
s5创建过程:在常量池中放一个"def",然后将常量池中的"abc"和"def"拼接成"abcdef"(原来的“abc”和"def"依然存在常量池),然后返回常量池"abcdef"的引用
2、构建超大字符串
StringBuffer内部加锁实现线程安全,性能比StringBuilder低不讨论,仅测试“+”号拼接和StringBuilder.append()拼接
例子
public static void main(String[] args) {
System.out.println("=====start=====");
long start = System.currentTimeMillis();
String s1 = "abcdefg";
for (int i=0;i<75000;i++){
s1 +=i;
}
long s1End = System.currentTimeMillis();
System.out.println("=====s1 end, take time "+(s1End-start)+"=====");
StringBuilder s2 = new StringBuilder("abcdefg");
for (int i=0;i<75000;i++){
s2.append(i);
}
long s2End = System.currentTimeMillis();
System.out.println("=====s2 end, take time "+(s2End-s1End)+"=====");
}
结果
=====start=====
=====s1 end, take time 9789=====
=====s2 end, take time 2=====
原理
"+"号拼接会在每次循环创建一个StringBuilder对象,性能差距主要在创建对象上
"+"拼接的部分字节码
L6
LINENUMBER 11 L6
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
ALOAD 3
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
ILOAD 4
INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ASTORE 3
append拼接的部分字节码
L13
LINENUMBER 17 L13
ALOAD 6
ILOAD 7
INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;
POP
3、正则匹配优化
待完善