栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

StringBuilder和String字符串拼接的底层原理分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

StringBuilder和String字符串拼接的底层原理分析

StringBuilder和String字符串拼接的底层原理分析 1.String类 1.1 String类型数据的比较

​ 例如下列代码

String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
sout(str1==str2);
sout(str1==str3);

​ 结果为true和false,原因是因为,str1和str2是直接赋值,当str1赋值时,会优先检查串池中是否存在abc字符串,若存在则之直接将串池中的地址赋值给str1,若不存在则在串池中生成对应的空间来保存该字符串,这样当str2进行赋值为abc时,会优先将串池中的该字符串的地址赋值给str2,这样str1和str2进行比较地址时,就发现地址相同,所以为true,而str3是使用new创建的字符串,这样就会在堆中创建一个新的字符串对象来保存该字符,这样str3中保存的地址是堆中的地址,所以进行比较的时候就不相同,所以为false。

​ 总结来说:直接赋值,会复制字符串常量池中的内容,new出来的不会复用,而是开辟一个新的空间,==号对于引用数据类型来说比较的是地址值。

1.2 String类的数据拼接
String str = "a"+"b"+"c";

​ 上诉代码进行字符串拼接未出现变量,在jvm编译的形成class文件的时候实际上就相当于:

String str = "abc"

​ 所以上述的字符串是属于串池管理

String str = "abc";
String str1 = str + "def";

​ 上诉代码进行字符串拼接的时候,含有变量,则拼接的原理是首先在堆中创建一个StringBuilder对象,这里命名为sb,然后通过StringBuilder对象的append方法将str添加进sb,而后在使用append方法将def字符串也添加进sb中,最后在调用toString方法,将sb转为String类型返回,这样就会额外的创建了两个对象。如果上诉的拼接过程出现多次,就会产生大量的StringBuilde和String类型的对象,大大的降低了效率。

2. StringBuilder 2. 1StringBuilder的实现原理

​ StringBuilder的实现过程是首先创建一个默认容量为16字节的数组,当添加的内容的长度小于16时,直接添加,当添加的内容大于16时,进行扩容,扩容的方法为:原来的容量*2+2.

StringBuilder sb = new StringBuilder();
sout(sb.length);
sout(sb.capacity());
上述代码执行的结果为:0   16
这是因为刚刚创建的StringBuilder对象,里面的内容为空,所以长度为0,容量为初始值16

在StringBuilder类中提供了空参构造方法

public StringBuilder(){
    super(16);
}

在AbstractStringBuilder类中
AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}

//通过上诉代码可以看出,StringBuilder默认创建一个容量为16字节的数组
2.2 StringBuilder实现字符串的拼接

​ StringBuilder中的append方法的实现分析

   public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
//获取用户输入的值,然后调用super.append方法

    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
//首先判断传入的字符串是否为null,如果则调用appendNull方法
    private AbstractStringBuilder appendNull() {
        int c = count;
        ensureCapacityInternal(c + 4);
        final char[] value = this.value;
        value[c++] = 'n';
        value[c++] = 'u';
        value[c++] = 'l';
        value[c++] = 'l';
        count = c;
        return this;
    }
//会将null的值进行赋值,然后返回
//否则则会先计算输入的字符串的长度,然后加上原来的长度count,从而的到目前所需要的最小的容量,在调用ensureCapacityInternal方法
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }
//在ensureCapacityInternal方法中会判断所需要的最小的空间容量减去原来的空间容量,来确定是否能够装下,如果能够装下,则条件判断不成立,就不进行扩容,否则则进行扩容,最后将字符串添加进数组,然后修改数组的长度即可。

总结来说:使用StringBuilder来进行字符串的拼接效率比String的效率大大提高,其原理就是因为String需要开辟大量的空间,而StringBuilder则是使用数组来完成拼接的操作,不需要开辟额外的空间,StringBuilder的空间范围为int的最大值。这一点在JavaScript中可以类比,使用数组完成字符串拼接,效率更高。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1007742.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号