网站首页 > 精选教程 正文
作者 | 浩说编程
来源 | 公众号:浩说编程
[ 大厂技术资源 | 研发必备安装包 | 限时免费获取 ]
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
123
相信大家都知道答案,重点来拆解一下每一步的底层逻辑:
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");
}
12345
创建 a 变量时,调用 new Sting() 会在堆内存中创建一个 String 对象,String 对象中的 char 数组将会引用常量池中字符串。在调用 intern 方法之后,会去常量池中查找是否有等于该字符串对象的引用,有就返回引用。
创建 b 变量时,调用 new Sting() 会在堆内存中创建一个 String 对象,String 对象中的 char 数组将会引用常量池中字符串。在调用 intern 方法之后,会去常量池中查找是否有等于该字符串对象的引用,有就返回引用。
而在堆内存中的两个对象,由于没有引用指向它,将会被垃圾回收。所以 a 和 b 引用的是同一个对象。
三、纠正字符串拼接误区
按照正常的理解,由于String不可变,那么每次运算操作都应该产生了一个新的对象,事实真的如此吗?
String str = "a" + "b" + "c";
1
我将上面代码编译成的class文件通过反编译之后的结果:
String str = "abc";
1
所以事实是:在拼接String常量的时候,编译器对代码进行了优化,将字符串合并了。
我们再试一下拼接变量的效果:
String b = "b";
String str = "a" + b + "c";
12
编译之后:
String b = "b";
String str = (new StringBuilder()).append("a").append(b).append("c");
12
虽然编译器对String进行了优化,不过还是建议显示的使用StringBuffer或StringBuilder。
四、字符串分割的最优解
对于字符串的分割,我在上一篇讲到过split()方法中正则表达式的回溯引起的效率问题,所以建议采用indexOf()方法作字符串分割。
作者 | 浩说编程
来源 | 公众号:浩说编程
[ 大厂技术资源 | 研发必备安装包 | 限时免费获取 ]
- 上一篇: Java基础面试:一文看懂String类中的常用方法
- 下一篇: java string 深入解析
猜你喜欢
- 2024-11-18 Python学习(十)字符串的常用操作详解「Ⅱ」
- 2024-11-18 java基础—string,值得java初学者收藏的文章
- 2024-11-18 Java将 PDF 拆分为多个 PDF 文件
- 2024-11-18 「LeetCode」分割回文串 II Java题解
- 2024-11-18 【算法题】1593. 拆分字符串使唯一子字符串的数目最大
- 2024-11-18 《Java程序设计》课程代码题(一)
- 2024-11-18 JAVA后台开发的瑞士军google guava 集合,字符串实测
- 2024-11-18 Java字符串相关面试题
- 2024-11-18 LeetCode笔记|131:分割回文串
- 2024-11-18 Java基础学习之与字符串相关的正则表达式
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)