Java性能调优--代码篇:String内存优化

作者 | 浩说编程
来源 | 公众号:浩说编程
[ 大厂技术资源 | 研发必备安装包 | 限时免费获取 ]

在这里插入图片描述

String在日常开发中的使用频率应该不需要我过多形容,大家闭着眼睛都能手写出来,但也正因如此,对于String的性能优化最容易被忽视却也最为必要!
如何优化String的内存开支?
怎样用更少的空间管理String?
让我们带着这几个问题开始本篇的探讨。

 

一、String自身的“优化”设计思想

“String 和 StringBuffer 有什么区别?”

“StringBuffer可变,String不可变。”

“String为什么不可变?”

“额…”

这是一段面试的真实案例,面试者直接被pass掉,这也反映了一个普遍的问题:“知其然而不知其所以然”,希望大家引以为鉴,下面就来探讨一下“String为什么不可变?”

先从一个例子开始:

String str_1 = "abc";
String str_2 = "abc";
System.out.print(str_1==str_2);//true

相信大家都知道答案,重点来拆解一下每一步的底层逻辑:

1、String str_1 = “abc”;

首先,在常量池中查询"abc"是否已存在:
图片
发现不存在,于是将"abc"初始化到常量池中,str_1引用该内容:
图片

2、String str_2 = “abc”;

再次创建相同字符串"abc",同样在常量池中查询"abc"是否已存在
图片

判断已经存在,于是不再重复创建内容,使用相同的引用
图片

于是得出答案true。

那么试想一下,如果String可变的话,这种常量池存放字符串,内容相同则不再开辟空间而是指向同一引用的设计思想是否还可行?
是不是即便创建了相同的字符串也要重新分配内存,造成不必要的内存损耗。这就是String自身的"优化"设计思想。

码文不易
你的关注是浩说编程持续更新的动力
浩说编程会做的更好

 

二、Stirng.intern:从20G到百兆内存消耗

该优化方法分享自全球知名社交平台推特(Twitter)的一名工程师,使用这种方法成功帮助他将String的内存消耗从20G降到几百兆。

我们通过代码来看一下intern方法做了什么:

String a = new String("abc").intern();
String b = new String("abc").intern();
if(a==b) {
    System.out.print("a==b");
}

创建 a 变量时,调用 new Sting() 会在堆内存中创建一个 String 对象,String 对象中的 char 数组将会引用常量池中字符串。在调用 intern 方法之后,会去常量池中查找是否有等于该字符串对象的引用,有就返回引用。

创建 b 变量时,调用 new Sting() 会在堆内存中创建一个 String 对象,String 对象中的 char 数组将会引用常量池中字符串。在调用 intern 方法之后,会去常量池中查找是否有等于该字符串对象的引用,有就返回引用。

而在堆内存中的两个对象,由于没有引用指向它,将会被垃圾回收。所以 a 和 b 引用的是同一个对象。

 

三、纠正字符串拼接误区

按照正常的理解,由于String不可变,那么每次运算操作都应该产生了一个新的对象,事实真的如此吗?

String str = "a" + "b" + "c";

我将上面代码编译成的class文件通过反编译之后的结果:

String str = "abc";

所以事实是:在拼接String常量的时候,编译器对代码进行了优化,将字符串合并了。

我们再试一下拼接变量的效果:

String b = "b";
String str = "a" + b + "c";

编译之后:

String b = "b";
String str = (new StringBuilder()).append("a").append(b).append("c");

虽然编译器对String进行了优化,不过还是建议显示的使用StringBuffer或StringBuilder。

 

四、字符串分割的最优解

对于字符串的分割,我在上一篇讲到过split()方法中正则表达式的回溯引起的效率问题,所以建议采用indexOf()方法作字符串分割。

作者 | 浩说编程
来源 | 公众号:浩说编程
[ 大厂技术资源 | 研发必备安装包 | 限时免费获取 ]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值