StringBuilder 你不知道的骚操作

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏精讲JAVA

揭开Java 泛型类型擦除神秘面纱

大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很...

13510
来自专栏破晓之歌

JAVA入门3-2(未完,待续) 原

List(序列)、Queue(队列)可重复排列有序的,Set(集)不可重复无序。list和set常用。

11850
来自专栏小樱的经验随笔

彻底搞定C语言指针(精华版)

1.语言中变量的实质 要理解C指针,我认为一定要理解C中“变量”的存储实质, 所以我就从“变量”这个东西开始讲起吧! 先来理解理解内存空间吧!请看下图: ...

44330
来自专栏Java架构沉思录

关于泛型,你可能不知道的事儿

大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很...

12210
来自专栏Ryan Miao

Java8-如何构建一个Stream

Stream的创建方式有很多种,除了最常见的集合创建,还有其他几种方式。 List转Stream List继承自Collection接口,而Collection...

38740
来自专栏Java架构师历程

精选30道Java笔试题解答

都是一些非常非常基础的题,是我最近参加各大IT公司笔试后靠记忆记下来的,经过整理献给与我一样参加各大IT校园招聘的同学们,纯考Java基础功底,老手们就不用进来...

37640
来自专栏C/C++基础

C++引用计数(reference counting)技术简介(3)

要想将引用计数施加到现有的实值对象Widget上,按照前面讨论的,都需要修改Winget类的源代码。但是,有时程序库的内容不是我们呢可以修改的,又该如何做呢?

8210
来自专栏Java Web

Java学习笔记(3)—— String类详解

前言 因为没有成功地为IDEA配上反编译工具,所以自己下载了一个XJad工具,背景是白色的,所以忍着强迫症硬是把IDEA的主体也给换成白色了,感觉为了这篇文章...

28950
来自专栏老司机的技术博客

golang学习笔记3:常量与变量

常量使用关键字 const 定义,用于存储不会改变的数据。 存储在常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。 常量的定义格式: ...

11610
来自专栏个人随笔

深入理解Java异常处理机制 (笼统篇)

9210

扫码关注云+社区

领取腾讯云代金券