正确使用String、StringBuffer、StringBuilder

《编写高质量代码 改善java程序员的151个建议》

String类是不可改变的量,比如创建了一个“abc”这样的字符串对象,那么它在内存中永远都会是“abc”这样具有固定表面值的一个对象,不能被修改。即使想通过string提供的方法来尝试修改,要么创建一个新的字符串对象,要么返回自己。比如:public String substring(int beginIndex)方法。

public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }

String str1 = "中国";
		String str2 = "中国";
		String str3 = new String("中国");
		String str4 = str3.intern();
		System.out.println(str1 == str2);
		System.out.println(str1 == str3);
		System.out.println(str1 == str4);
输出结果为 true false true

创建一个字符串时,首先检查池中是否有字面值相等的字符串,如果有,则不再创建,直接返回池中该对象的引用,若没有则创建值,然后放到池中,并返回新建对象的引用。通过new String("中国");这种方式 是不会检查字符串池的,也不会把对象放到池中。

通过intern方法,会检查当前的对象在对象池中是否有字面值相同的引用对象,如果有则返回池中对象,如果没有则放置到对象池中,并返回当前对象。


StringBuffer是一个可变字符序列,它与String一样,在内存中保存的都是一个有雪的字符序列(char类型的数组)。

StringBuilder和StringBuffer基本相同,都是可变字符序列,不同点是:StringBuffer 是线程安全的,StringBuilder是线程不安全的,StringBuffer的方法前都有synchronized关键字,所以性能远低于StringBuilder。

三者使用的场景如下:

(1)使用String的场景

在字符串不经常变化的场景中可以使用String类,例如常量的声明、少量的变量运算等。

(2)使用StringBuffer类的场景

在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在多线程的环境中,例如xml解析、http参数解析和封装等。

(3)使用StringBuilder类的场景

在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在单线程的环境中,如SQL语句的拼装、josn的封装等。


字符串拼接方式:+,concat,append

System.out.println("start=" + System.currentTimeMillis());
		StringBuffer sb = new StringBuffer("a");
		for (int i = 0; i < 50000; i++) {
			sb.append("c");

		}

		System.out.println("enddd=" + System.currentTimeMillis());

		System.out.println("---------------------------------");
		System.out.println("start=" + System.currentTimeMillis());
		String str = "a";
		for (int i = 0; i < 50000; i++) {
			str += "c";
		}
		System.out.println("enddd=" + System.currentTimeMillis());

		System.out.println("---------------------------------");
		System.out.println("start=" + System.currentTimeMillis());
		String string = "a";
		for (int i = 0; i < 50000; i++) {
			string.concat("c");
		}

		System.out.println("enddd=" + System.currentTimeMillis());

循环5w次,+耗时最长,concat次之,append耗时最短。

(1)“+”方法拼接字符串

实现方式:

str = new StringBuilder(str).append("c").toString();

它与纯粹使用StringBuilder的append方法是不同的:一是每次循环都会创建一个StringBuilder对象,二是每次执行完毕都要调用toString方法将其转换为字符串---它的执行时间就是耗费在这里了。

(2)concat方法拼接

public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }

每次会创建String对象,所以速度会慢。

(3)append

public AbstractStringBuilder append(String str) {
        if (str == null) str = "null";
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
只有字符串的拼接,没有产生新的对象。

适当的场景使用适当的字符串拼接方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值