字符串性能优化
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() 方法时,对回溯问题加以重
视就可以了
结尾更容易懂
题解
相关文章:

字符串性能优化
String 对象作为 Java 语言中重要的数据类型,是内存中占据空间最大的一个对象。高效地 使用字符串,可以提升系统的整体性能。 来一到题来引出这个话题 通过三种不同的方式创建了三个对象,再依次两两匹配,每组被匹配的两个对象是否…...

从零开始理解Linux中断架构(23)中断运行临界区和占先调度
Linux在内核中定义了6种运行临界区。 in_interrupt in_interrupt在驱动中使用频率最高的函数了,in_interrupt()就是指示Core是否正在中断处理中,包含了硬中断,软中断运行临界区。如果在中断处理中,则不能调用__do_softirq执行软中断处理。硬中断中不可调度不可中断,所有…...
(3)Gymnasium--CartPole的测试基于DQN
1、使用Pytorch基于DQN的实现 1.1 主要参考 (1)推荐pytorch官方的教程 Reinforcement Learning (DQN) Tutorial — PyTorch Tutorials 2.0.1cu117 documentation (2) Pytorch 深度强化学习 – CartPole问题|极客笔记 2.2 pytorch官方的教程原理 待续,这两天时…...

利用sklearn 实现线性回归、非线性回归
代码: import pandas as pd import numpy as np import matplotlib import random from matplotlib import pyplot as plt from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression# 创建虚拟数据 x np.array(r…...

Java课题笔记~ MyBatis入门
一、ORM框架 当今企业级应用的开发环境中,对象和关系数据是业务实体的两种表现形式。业务实体在内存中表现为对象,在数据库中变现为关系数据。当采用面向对象的方法编写程序时,一旦需要访问数据库,就需要回到关系数据的访问方式&…...

Activity的自启动模式
以下内容摘自郭霖《第一行代码》第三版 文章目录 Activity的自启动模式1.standard(默认)2.singleTop3.singleTask4.singleInstance Activity的自启动模式 启动模式一共有4种,分别是standard、singleTop、singleTask和singleInstance&#x…...
53数组的扩展
数组的扩展 扩展运算符Array.from()Array.of()实例方法:copyWithin()实例方法:find(),findIndex(),findLast(),findLastIndex()实例方法:fill()[实例方法:entries(),keys() 和 valu…...
Rust调试【三】
Local Debug: vscode CodeLLDB extension memory leak analysis: Rust and Valgrind FFI Memory wrapping: Foreign Function Interface FFI panic handling: Panic handling...

uniApp 对接安卓平板刷卡器, 读取串口数据
背景: 设备: 鸿合 电子班牌 刷卡对接 WS-B22CS, 安卓11; 需求: 将刷卡器的数据传递到自己的App中, 作为上下岗信息使用, 以完成业务; 对接方式: 1. 厂家技术首先推荐使用 接收自定义广播的方式来获取, 参考代码如下 对应到uniApp 中的实现如下 <template><view c…...
Go new 与 make
Go new 与 make 在Go语言中,"new"和"make"都是用于动态分配内存的关键字,但它们有不同的用途和区别。 "new": 在Go语言中,"new"是一个内建函数,用于值类型(基本类型和用户定…...

centos系统离线安装k8s v1.23.9最后一个版本并部署服务,docker支持的最后一个版本
注意:我这里的离线安装包是V1.23.9. K8S v1.23.9离线安装包下载: 链接:https://download.csdn.net/download/qq_14910065/88139255 这里包括离线安装所有的镜像,kubeadm,kubelet 和kubectl,calico.yaml&am…...

(学习笔记-内存管理)如何避免预读失效和缓存污染的问题?
传统的LRU算法存在这两个问题: 预读失效 导致的缓存命中率下降缓存污染 导致的缓存命中率下降 Redis的缓存淘汰算法是通过实现LFU算法来避免 [缓存污染] 而导致缓存命中率下降的问题(redis 没有预读机制) Mysql 和 Linux操作系统是通过改进…...
【arthas】入门与实战(一)
arthas 一、安装1. 安装与启动二、具体应用1.查看 dashboard1.1 各区域详解2.查看jvmweb访问查询垃圾回收器具体内容和大概的操作官网上都有,下面记录的是自己的一些操作、思考和查找的资料,帮助理解。 官网文档:https://arthas.aliyun.com/doc/ 一、安装 1. 安装与启动 …...

vim、awk、tail、grep的使用
vim命令 $定位到光标所在行的行末^定位到光标所在行的行首gg定位到文件的首行G定位到文件的末行dd删除光标所在行ndd删除n行(从光标所在行开始)D删除光标所在行,使之变为空白行x删除光标所在位置字符nx删除n个字符,从光标开始向后…...

vue拖拽改变宽度
1.封装组件ResizeBox.vue <template><div ref"resize" class"resize"><div ref"resizeHandle" class"handle-resize" /><slot /></div> </template> <script> export default {name: Resi…...

华为数通HCIA-ARP(地址解析协议)详细解析
地址解析协议 (ARP) ARP (Address Resolution Protocol)地址解析协议: 根据已知的IP地址解析获得其对应的MAC地址。 ARP(Address Resolution Protocol,地址解析协议)是根据IP地址获取数据链路层地址的一个…...

【Python机器学习】实验04(1) 多分类(基于逻辑回归)实践
文章目录 多分类以及机器学习实践如何对多个类别进行分类1.1 数据的预处理1.2 训练数据的准备1.3 定义假设函数,代价函数,梯度下降算法(从实验3复制过来)1.4 调用梯度下降算法来学习三个分类模型的参数1.5 利用模型进行预测1.6 评…...

【ChatGLM_01】ChatGLM2-6B本地安装与部署(大语言模型)
基于本地知识库的问答 1、简介(1)ChatGLM2-6B(2)LangChain(3)基于单一文档问答的实现原理(4)大规模语言模型系列技术:以GLM-130B为例(5)新建知识库…...
谷歌Tsunami(海啸)扫描器搭建扩展使用教程
目录 介绍 下载地址 功能总结 原理 服务探测 漏洞检测 安装...

诚迈科技承办大同首届信息技术产业峰会,共话数字经济崭新未来
7月28日,“聚势而强共领信创”2023大同首届信息技术产业峰会圆满举行。本次峰会由中共大同市委、大同市人民政府主办,中国高科技产业化研究会国际交流合作中心、山西省信创协会协办,中共大同市云冈区委、大同市云冈区人民政府、诚迈科技&…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...

c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...