java基础(一)String,StringBuffer,StringBuilder

String

== 问题

	        String str1 = "hello world";
		String str2 = "hello world";
		String str3 = new String("hello world");
		System.out.println(str1==str2);//true
		System.out.println(str1==str3);//false
string有个字符串常量池的概念,例如这个方式创建string对象 str = "hello world",会放到字符串常量池中,下次调用的时候,

str2 = "hello world",直接从字符串常量池中取值,就是上面的str2,str1两个引用指向的是共同一个对象。

new String();则是创建对象放到堆中,不管堆中是否已有这个对象

String对象的改变

 public String concat(String str) {
	int otherLen = str.length();
	if (otherLen == 0) {
	    return this;
	}
	char buf[] = new char[count + otherLen];
	getChars(0, count, buf, 0);
	str.getChars(0, otherLen, buf, count);
	return new String(0, count + otherLen, buf);
    }
 public String substring(int beginIndex, int endIndex) {
	if (beginIndex < 0) {
	    throw new StringIndexOutOfBoundsException(beginIndex);
	}
	if (endIndex > count) {
	    throw new StringIndexOutOfBoundsException(endIndex);
	}
	if (beginIndex > endIndex) {
	    throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
	}
	return ((beginIndex == 0) && (endIndex == count)) ? this :
	    new String(offset + beginIndex, endIndex - beginIndex, value);
    }
从源码看出,string对象的改变,都是创建一个新的对象

StringBuilder

 public StringBuilder() {
	super(16);
    }
 AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }
 public AbstractStringBuilder append(String str) {
	if (str == null) str = "null";
        int len = str.length();
	if (len == 0) return this;
	int newCount = count + len;
	if (newCount > value.length)
	    expandCapacity(newCount);
	str.getChars(0, len, value, count);
	count = newCount;
	return this;
    }
 void expandCapacity(int minimumCapacity) {
	int newCapacity = (value.length + 1) * 2;
        if (newCapacity < 0) {
            newCapacity = Integer.MAX_VALUE;
        } else if (minimumCapacity > newCapacity) {
	    newCapacity = minimumCapacity;
	}
        value = Arrays.copyOf(value, newCapacity);
    }
 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;
    }
默认情况下,容量为16,使用append方法时候,执行expandCapacity方法保证容量,如果超出容量的话会创建新的char数组,并将旧的字符数组copy到新的数组内

线程安全

 public synchronized StringBuffer append(String str) {
	super.append(str);
        return this;
    }
 public synchronized StringBuffer append(StringBuffer sb) {
        super.append(sb);
        return this;
    }
----------------------------------------------------------------------------------------------------------------------------------

 private StringBuilder append(StringBuilder sb) {
	if (sb == null)
            return append("null");
	int len = sb.length();
	int newcount = count + len;
	if (newcount > value.length)
	    expandCapacity(newcount);
	sb.getChars(0, len, value, count);
	count = newcount;
        return this;
    }
 public StringBuilder append(String str) {
	super.append(str);
        return this;
    }
可以看出StringBuffer append方法是加了synchronized同步锁,是线程安全的,单线程环境下,建议使用StringBuild性能更高

StringBuffer 和 StringBuild的toString()方法

 public synchronized String toString() {
	return new String(value, 0, count);
    }
 public String toString() {
        // Create a copy, don't share the array
	return new String(value, 0, count);
    }
tostring方法是直接创建string对象

性能测试

1. 间接相加和直接相加

	        String a = " hello ";
		String b = " ni ";
		String c = " hao ";
		String str2 = " hello "+ " ni "+ " hao ";
		String str1 = a+b+c;

编译后:


从反编译的结果看出加号拼接的编译器会直接优化,后面a+b+c的方式则是创建stringbuilder使用append拼接,最后tostring,显然前面的性能更好

2. a+"hello"+"world"方式

		String a = " hello ";
		String b = " ni ";
		String c = " hao ";
		String str2 = " hello "+ " ni "+ " hao ";
		String str1 = a+" ni "+" hao ";
反编译结果:


从反编译结果看,a +" hello " +" world " 也会去创建stringbuilder,append拼接,最后调用tostring创建对象,并没有起到优化的效果

但是如果将a 改为final 

		final String  a = " hello ";
		String b = " ni ";
		String c = " hao ";
		String str2 = " hello "+ " ni "+ " hao ";
		String str1 = a+" ni "+" hao ";
反编译结果如下,可以看出final 修饰字符串,+拼接,jvm会进行优化,str1==str2结果是true,是同一个对象


3. 比较循环中+和append的效率

 public static void main(String[] args) {
	        run1();
	        run2();
	    }
	    
	    public static void run1() {
	        long start = System.currentTimeMillis();
	        String result = "";
	        for (int i = 0; i < 10000; i++) {
	            result += i;
	        }
	        System.out.println(System.currentTimeMillis() - start);
	    }

	    public static void run2() {
	         long start = System.currentTimeMillis();
	        StringBuilder builder = new StringBuilder();
	        for (int i = 0; i < 10000; i++) {
	            builder.append(i);
	        }
	        System.out.println(System.currentTimeMillis() - start);
	    }
执行结果:append的效率更快,从run1的反编码可以看出,每次都要初始化stringbuilder,然后相加,效率更低

4. stringbuffer,stringbuilder初始化容量

前面有介绍过,stringbuilder,stringbuffer默认容量是16个长度,如果在创建时候,就指定了容量,就避免由于容量不足,创建新的字符数组的开销。

public class Demo3 {
    public static void main(String[] args) {
        test1();
        test2();
    }

    public static void test1() {
        StringBuilder sb = new StringBuilder(7000000);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            sb.append("jiajun");
        }
        long end=System.currentTimeMillis()-start;
        System.out.println(end);
    }

    public static void test2() {

        StringBuilder sb = new StringBuilder();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            sb.append("jiajun");
        }
        long end=System.currentTimeMillis()-start;
        System.out.println(end);
    }
    //输出:18 26
}
最后总结

1. string对象创建的时候,如果使用new创建,会在堆中创建,不管有没有,而引号创建,会在字符串常量池中寻找,找到了,就将引用执行这个对象

2. 字符串直接相加的话,编译器会进行优化,间接相加的话,会创建stringbuilder,在append拼接

3. stringbuffer线程安全,但是牺牲了一些性能,stringbuilder线程非安全,但是在单线程环境下,性能更高

4.stringbuffer,stringbuilder 有默认容量,超出容量时候,会创建新的字符数组,进行复制


转载:http://www.cnblogs.com/-new/p/7417915.html














  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值