美文网首页Java 杂谈
StringBuilder 你不知道的骚操作

StringBuilder 你不知道的骚操作

作者: 三好码农 | 来源:发表于2018-07-24 11:46 被阅读12次

    StringBuilder为什么非你不可

    String你还需要知道这些细节中提到过,由于String被设计成immutable,所以才有了StringBuilder和StringBuffer这2个类来帮助我们操作字符串,StringBuilder线程不安全,StringBuffer线程安全,在我们大多数日常使用场景,都是单线程操作字符串,所以StringBuidler用的会多一些,而且编译器也会默认帮我们将+号字符串拼接转化为StringBuidler append,这篇文章我会跟大家分享我知道的StringBuilder使用的一些骚操作。

    先抛出3个问题

    • StringBuilder的底层实现?插入删除的效率如何?
    • StringBuilder的扩容策略?
    • StringBuilder为什么没有clear方法?有没有替代方法?

    StringBuilder的底层实现?插入删除的效率如何?

    这个问题只要看下Jdk的源码就能清楚


    StringBuilder实现数据结构.png

    底层数据结构很简单,就是一个char[] value 和大小字段 count,构造器生成的char[] 默认capacity大小是16,如果很明确插入的字符串很长,应该将capacity设置大一些,避免频繁拷贝数组扩容。

    接下来,我们看下StringBuilder 插入删除的实现


    StringBuilder insert.png StringBuilder delete.png

    可以看到,由于是基于数组实现的,所以插入删除的效率都不会太高,毕竟都要进行数组的拷贝,但是也不必太过担心,System.arrayCopy的速度还是很快的。

    这里我想提一点,append和insert方法都能增长字符串,该如何选择,看上面的源码可以看到,insert不论字符串插入的位置是在中间还是最后,都会进行数组拷贝,而append则会根据当前数组的长度来判断是否需要拷贝扩容,所以如果需要在尾部增加字符串使用append,其他位置使用insert。

    StringBuilder的扩容策略?

    我们看一下StringBuilder append方法


    StringBuilder 扩容.png

    可以看到,在字符数组大小不足够容纳新的字符的时候,会进行扩容,而扩容后的大小是原来数组的大小+新字符串的长度,所以这里的扩容策略是非常保守的,只能够容纳这一次的append操作,所以如果我们要在循环内频繁进行append操作,可以将StringBuilder初始大小capacity设置大一些,避免频繁扩容数组拷贝

    StringBuilder为什么没有clear方法?有没有替代方法?

    平常我们使用的Jdk集合类,如ArrayList,HashMap等都会有clear方法来清空数据,但是StringBuilder没有提供这个方法,那我们如何清空StringBuilder中的数据呢,难道非要循环去调用delete?当然不用,StringBuilder另外给我们提供了setLength方法,参数传0,就达到了清空数据的作用。


    StringBuilder 清空.png

    通过源码可以看到,setLength方法,当传入的新length小于原来的count时,只是简单的将count设为新length,并不会去动原来的字符数组value,相当于count是一个指针,只是在移动指针,避免了数组拷贝,效率比较高。这个又引出了一个新问题,既然setLength不会去改变value数组,那value占用的内存怎么释放呢?

    value占用的内存怎么释放

    StringBuilder 提供了trimToSize方法


    StringBuiler trim.png

    以上(安排的很明白),水平有限,各位大佬轻点喷😆

    相关文章

      网友评论

      • 沐小晨曦:可以,被安排的明明白白。保守的扩容机制,所以不要在循环中调用append方法。学到了学到了(。・ω・。)ノ♡
        三好码农:@沐小晨曦 :smile:天天向上

      本文标题:StringBuilder 你不知道的骚操作

      本文链接:https://www.haomeiwen.com/subject/oxuemftx.html