String+拼接,String.concat String.format StringBuffer StringBuilder的对比

1.加号+拼接

这个用法是最初学习当中最常用的方法。原来也一直在用。

后来有了代码规范,在log打印日志的地方,让使用模板形式的字符串拼接。

才因此引发的思考。

这种+连接的优缺点在哪。

优点:只是方便

缺点:String是一个不可变的类,这导致

有的人说:a+b+c 本质上是 new String + new String + new String 。。。。这使得过量创建对象。极限状态下,gc的速度赶不上new的速度,就oom了。

也有的人说:String直接相加已经都被编译器优化成StringBuilder了,只是循环里优化的不太合理。所以,String相加快还是StringBuilder快,其实只是StringBuilder调用方式对比。。。

这两个说法看起来应该似乎跟编译版本有关系,具体的还不了解。

支路:所以String不可变的意义是?

1.方便做hash中的key

因为 String 的 hash 值经常被使用,例如 String 用做 HashMap 的 key。不可变的特性可以使得 hash 值也不可变,因此只需要进行一次计算。

2.String pool的需要

如果String被创建了,从String pool中直接获取引用,只要String 不改变,才能从String pool获取

3.安全性

String 经常作为参数,String 不可变性可以保证参数不可变。例如在作为网络连接参数的情况下如果 String 是可变的,那么在网络连接过程中,String 被改变,改变 String 对象的那一方以为现在连接的是其它主机,而实际情况却不一定是。

4.线程安全

String 不可变性天生具备线程安全,可以在多个线程中安全地使用。

2.String.format

可读性非常好

效率:低于stringbuilder

String.format具有更大的重量,String.format首先使用正则表达式解析输入,然后填充参数。因为它创建了一个新的Formatter,解析了您的输入格式字符串,创建了一个StringBuilder,将所有内容附加到它并调用toString()。所以性能最差。

3.String.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);
    }

参数不可以是null,他没给使用者提供自动检测null的功能,会报npe

简单粗暴,直接Arrays.copyOf,直接内存复制,这根StringBuilder原理类似,但是它不用初始化StringBuilder对象,只是每次concat都会创建一个新的String对象,所以在有些情况下它比StringBuilder要快一点。

支路:Arrays.copyOf是什么?

是创建一个新的数组(也就是分配了一个新的内存空间),然后调用System.arraycopy()复制内容,赋值给新数组,然后返回新数组。

浅拷贝:增加一个指针,指向了原来已经存在的对象地址,gc之后容易给它误回收了。

深拷贝:将原对象完完整整copy出一份新对象,并指向他。之后跟原对象毫无关系。

4.StringBuilder

这是咱们推荐的String处理工具,效率综合最好。

但他的可读性。。。

支路:StringBuilder的原理?

String源码:private final char value[];

StringBuilder源码:

1.StringBuilder extends AbstractStringBuilder

他继承AbstractStringBuilder

2. char[] value;

他定义了一个char[],默认长度16,非final,非static。

3.ensureCapacityInternal()

private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));
    }
}

每次修改,先调用扩容函数

长度要不够用,就申请一个更大的空间,然后将原来的内容,浅拷贝给那片新的空间

4.getchars()

public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
{
    if (srcBegin < 0)
        throw new StringIndexOutOfBoundsException(srcBegin);
    if ((srcEnd < 0) || (srcEnd > count))
        throw new StringIndexOutOfBoundsException(srcEnd);
    if (srcBegin > srcEnd)
        throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
    System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}

修改String的最终方法,先判断是否空指针,再调用系统的System.arraycopy,上面的浅拷贝,本质也是调用的系统native方法。

public static native void arraycopy(Object src,  int  srcPos,
                                    Object dest, int destPos,
                                    int length);

5.StringBuffer

它和StringBuilder是同门兄弟,都继承与AbstractStringBuilder

咱们代码规范表示,除非的多线程,单线程禁用。

他如何实现的线程安全?

他使用了Synchronized锁住待编辑的String,与stringbuilder相比有额外负担的。

奇淫技巧:设置提示,当使用+连接时提示改用stringbuilder

 

注:以上内容都是我编的

参考文献:

1.String使用final修饰的好处:在java中为什么String是被final的_牛顿爱吃水果的博客-CSDN博客_java string为什么是final

2.java String、String.concat和StringBuilder性能对比:java String、String.concat和StringBuilder性能对比 - 走看看

3.String+,StringBuilder,String.format运行效率比较:String+,StringBuilder,String.format运行效率比较_锦聪的博客-CSDN博客_string.format效率

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值