字符串性能优化

news2024/11/16 19:25:06

String 对象作为 Java 语言中重要的数据类型,是内存中占据空间最大的一个对象。高效地
使用字符串,可以提升系统的整体性能。

来一到题来引出这个话题

通过三种不同的方式创建了三个对象,再依次两两匹配,每组被匹配的两个对象是否相等?
代码如下

结尾有东西

String 的不可变性

了解了 String 对象的实现后,你有没有发现在实现代码中 String 类被 final 关键字修饰
了,而且变量 char 数组也被 final 修饰了。
我们知道类被 final 修饰代表该类不可继承,而 char[] 被 final+private 修饰,代表了
String 对象不可被更改。Java 实现的这个特性叫作 String 对象的不可变性,即 String 对
象一旦创建成功,就不能再对它进行改变。

String 对象的优化

1. 如何构建超大字符串

字符串常量的累计

编程过程中,字符串的拼接很常见。前面我讲过 String 对象是不可变的,如果我们使用
String 对象相加,拼接我们想要的字符串,是不是就会产生多个对象呢?例如以下代码

分析代码可知:首先会生成 ab 对象,再生成 abcd 对象,最后生成 abcdef 对象,从理论
上来说,这段代码是低效的。

但实际运行中,我们发现只有一个对象生成,这是为什么呢?难道我们的理论判断错了?我
们再来看编译后的代码,你会发现编译器自动优化了这行代码,如下:

String str= "abcdef";

字符串变量的累计

上面我介绍的是字符串常量的累计,我们再来看看字符串变量的累计又是怎样的呢? 

上面的代码编译后,你可以看到编译器同样对这段代码进行了优化。不难发现,Java 在进
行字符串的拼接时,偏向使用 StringBuilder,这样可以提高程序的效率。

 综上已知:即使使用 + 号作为字符串的拼接,也一样可以被编译器优化成 StringBuilder
的方式。但再细致些,你会发现在编译器优化的代码中,每次循环都会生成一个新的
StringBuilder 实例,同样也会降低系统的性能。

所以平时做字符串拼接的时候,我建议还是要显示地使用 String Builder 来提升系统性
能。

如果在多线程编程中,String 对象的拼接涉及到线程安全,你可以使用 StringBuffer。但
是要注意,由于 StringBuffer 是线程安全的,涉及到锁竞争,所以从性能上来说,要比
StringBuilder 差一些

2 如何使用String.Intern节省内存

Twitter 每次发布消息状态的时候,都会产生一个地址信息,以当时 Twitter 用户的规模预
估,服务器需要 32G 的内存来存储地址信息。

考虑到其中有很多用户在地址信息上是有重合的,比如,国家、省份、城市等,这时就可以
将这部分信息单独列出一个类,以减少重复,代码如下 

通过优化,数据存储大小减到了 20G 左右。但对于内存存储这个数据来说,依然很大,怎
么办呢?

提供公共都有的部分

这个案例来自一位 Twitter 工程师在 QCon 全球软件开发大会上的演讲,他们想到的解决
方法,就是使用 String.intern 来节省内存空间,从而优化 String 对象的存储

具体做法就是,在每次赋值的时候使用 String 的 intern 方法,如果常量池中有相同值,就
会重复使用该对象,返回对象引用,这样一开始的对象就可以被回收掉。这种方式可以使重
复性非常高的地址信息存储大小从 20G 降到几百兆

 

为了更好地理解,我们再来通过一个简单的例子,回顾下其中的原理

输出结果:

a == b

在字符串常量中,默认会将对象放入常量池;在字符串变量中,对象是会创建在堆内存中,
同时也会在常量池中创建一个字符串对象,复制到堆内存对象中,并返回堆内存对象引用。

如果调用 intern 方法,会去查看字符串常量池中是否有等于该对象的字符串,如果没有,
就在常量池中新增该对象,并返回该对象引用;如果有,就返回常量池中的字符串引用。堆
内存中原有的对象由于没有引用指向它,将会通过垃圾回收器回收.

了解了原理,我们再一起看看上边的例子。

在一开始创建 a 变量时,会在堆内存中创建一个对象,同时会在加载类时,在常量池中创
建一个字符串对象,在调用 intern 方法之后,会去常量池中查找是否有等于该字符串的对
象,有就返回引用。
在创建 b 字符串变量时,也会在堆中创建一个对象,此时常量池中有该字符串对象,就不
再创建。调用 intern 方法则会去常量池中判断是否有等于该字符串的对象,发现有等
于"abc"字符串的对象,就直接返回引用。而在堆内存中的对象,由于没有引用指向它,将
会被垃圾回收。所以 a 和 b 引用的是同一个对象。

下面我用一张图来总结下 String 字符串的创建分配内存地址情况:

 使用 intern 方法需要注意的一点是,一定要结合实际场景。因为常量池的实现是类似于一
个 HashTable 的实现方式,HashTable 存储的数据越大,遍历的时间复杂度就会增加。如
果数据过大,会增加整个字符串常量池的负担。

3. 如何使用字符串的分割方法?

最后我想跟你聊聊字符串的分割,这种方法在编码中也很最常见。Split() 方法使用了正则
表达式实现了其强大的分割功能,而正则表达式的性能是非常不稳定的,使用不恰当会引起
回溯问题,很可能导致 CPU 居高不下。
所以我们应该慎重使用 Split() 方法,我们可以用 String.indexOf() 方法代替 Split() 方法完
成字符串的分割。如果实在无法满足需求,你就在使用 Split() 方法时,对回溯问题加以重
视就可以了

结尾更容易懂

题解

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/814728.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Eclipse使用Ctrl键导致程序卡死的解决方案

在Eclipse中,经常可以使用Ctrl鼠标单击,可以直接将编辑界面引导到相关的方法,属性,或者类。 这个功能确实非常好用,但是由于复制粘贴的功能快捷键也是Ctrl,以致我在快速进行操作的时候,Eclipse…

tinkerCAD案例:27. Build a Mobile Amplifier 构建移动放大器(2)

tinkerCAD案例:27. Build a Mobile Amplifier 构建移动放大器(2) 原文 step 1 Lesson Overview: 课程概述: Now we’re going to adapt the shape to your device! 现在,我们将根据您的设备调整形状! step 2 o create an in…

【雕爷学编程】MicroPython动手做(25)——语音合成与语音识别2

知识点:什么是掌控板? 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED…

浏览器安装selenium IDE插件并进行网页测试记录

Chrome开发者工具插件,谷歌浏览器开发者工具插件推荐下载_安装_教程-扩展迷 去官网直接搜索下载需要的插件就可。 插件下载安装-Chrome-扩展迷 下载好后解压: 打开Chrome谷歌浏览器: 设置>拓展程序>打开"开发者模式”>将下载好的seleni…

【多模态】21、BARON | 通过引入大量 regions 来提升模型开放词汇目标检测能力(CVPR2021)

文章目录 一、背景二、方法2.1 主要过程2.2 Forming Bag of Regions2.3 Representing Bag of Regions2.4 Aligning bag of regions 三、效果 论文:Aligning Bag of Regions for Open-Vocabulary Object Detection 代码:https://github.com/wusize/ovdet…

SciencePub学术 | 人工智能类重点SCIEEI征稿中

SciencePub学术 刊源推荐: 人工智能类重点SCIE&EI征稿中!信息如下,录满为止: 一、期刊概况: 人工智能类重点SCIE&EI 【期刊简介】IF:6.5-7.0,JCR1区,中科院2区; 【出版社…

画架构图工具-haydn

Haydn解决方案数字化平台_海顿解决方案工具链-华为云 下图为haydn架构图示例 Haydn解决方案数字化平台_海顿解决方案工具链-华为云 1、vpc是一个很重要的元素,有网络隔离的作用。 2、OBS、CES、CTS,不需要画到vpc里面。 3、不在区域内的资源&#xf…

Panda 编译时原子化 CSS-in-JS 框架的跨平台方案

Panda 编译时原子化 CSS-in-JS 框架的跨平台方案 Panda 编译时原子化 CSS-in-JS 框架的跨平台方案 对编译时原子化CSS框架的思考编译时 CSS-in-JS 方案对比 LinariaPandacss总结 weapp-pandacss 介绍快速开始 pandacss 安装和配置 0. 安装和初始化 pandacss1. 配置 postcss2. …

Hbase pe 压测 OOM问题解决

说明:本人使用CDH虚拟机搭建了Hbase集群,但是在压测的时发现线程多个的时候直接回OOM,记录一下 执行命令 hbase pe --nomapred --oneContrue --tablerw_test_1 --rows1000 --valueSize100 --compressSNAPPY --presplit10 --autoFlushtrue randomWrite …

SDXL 1.0 介绍和优缺点总结

2023年7月26日:Stability. AI 发布SDXL 1.0,这是对其生成模型的又一次重大更新,带来了突破性的变化。 SDXL 1.0包括两种不同的模型: sdxml -base-1.0:生成1024 x 1024图像的基本文本到图像模型。基本模型使用OpenCLIP-ViT/G和CLIP-ViT/L进行文本编码。…

详解c++继承与多继承

目录 🚄什么是继承🚉继承的概念🚃继承的定义 🚇继承基类成员访问方式的变化🚆基类和派生类对象赋值转换🚐继承时的作用域🚗派生类的默认成员函数🚓继承、友元、静态成员&#x1f69a…

运维级影像归档与通信系统(PACS)源码

运维级医院PACS系统源码,带演示,带使用手册和操作说明书 ,带三维重建与还原功能,开发环境:VC MSSQL。 一、影像归档与通信系统(PACS)概述 PACS影像归档与通信系统”( Picture Archiving and C…

小型双轮差速底盘灭火功能的实现

1. 功能说明 灭火机器人是一种特殊的机器人,专门用于进行火灾扑救和灭火任务。它们通常具备以下功能和特点: ① 火灾侦测:灭火机器人配备了各种传感器和探测设备,可以检测烟雾、温度升高等火灾迹象。 ② 火灾扑救:灭火…

cadence virtuoso layout MOS串联线在layout中合并(merge)掉

如图,net10合并掉 解决办法: shiftE,取消勾选Abut server,save

第六章应用层

1.应用层概述 应用层是计算机网络体系结构的最顶层,是设计和建立计算机网络的最终目的,也是计算机网络中发展最快的部分。 早期基于文本的应用(电子邮件、远程登录、文件传输、新闻组) 20世纪90年代将因特网带入千家万户的万维网www 当今流行的即时通信…

彻底解决IDEA输出中文乱码问题

本文一共有3种方法,针对的情况是输出中文乱码问题 问题描述 无法正确输出中文字符:(请正确分辨自己是哪一种乱码问题!) 解决方法 1、最容易想到 File -> Settings -> File Encodings下设置编码格式为UTF-8…

安卓:JzvdStd——网络视频播放器

目录 一、JzvdStd介绍 JzvdStd的特点和功能: JzvdStd常用方法: 二、JzvdStd使用 1、补充知识: 例子: MainActivity : VideoPageAdapter : activity_main: video_page: …

如何在C#中处理空值

在任何编程语言中开发应用程序时,经常会遇到空异常或空引用异常。空指针或空引用是指不引用有效的内存位置或对象的指针。这是一个困扰程序员已经很久的问题,自从程序员开始编写程序以来。空值是一个特殊的值,表示没有有效值可用。当将空值赋…

hbuilderx主题色分享-github风格

效果 步骤 hbuilderx总共有三种主题,绿柔主题Default,酷黑主题Monokai,雅黑主题Atom One Dark,修改主题色是基于三种主题之一的,不能直接创建一个新主题,比如下方配置是基于Atom One Dark(对象名为[Atom One Dark]),则当前hbuild…

【Sortable】前端拖拽库 | 简洁 | 实用 | 强大

前言 官网 - http://www.sortablejs.com/index.html中文文档 - https://www.itxst.com/sortablejs/neuinffi.htmlnpm - https://www.npmjs.com/package/sortablejs npm下载 npm i sortablejsumd <script src"https://www.itxst.com/package/sortable/sortable.min.js…