String、StringBuffer、StringBuilder 区别
在 Java 编程中,String、StringBuffer 和 StringBuilder 是处理字符串时常用的类。它们在功能上有相似之处,但在内部实现、性能、线程安全性等方面存在显著差异。理解这些差异有助于开发者在不同的场景下做出合适的选择,提高代码的性能和效率。
1. 内部实现
String
String 类是 Java 中不可变对象,一旦创建,其值不能被修改。String 类内部使用一个 final 修饰的字符数组来存储字符串内容,代码示例如下:
private final char value[];
这意味着每次对 String 对象进行修改操作(如拼接、替换等)时,实际上是创建了一个新的 String 对象,原对象保持不变。例如:
String str = "Hello";
str = str + " World";
在这个过程中,首先创建了一个内容为 "Hello" 的 String 对象,然后执行拼接操作时,会创建一个新的 String 对象,其内容为 "Hello World",原对象 "Hello" 仍然存在于内存中。
StringBuffer 和 StringBuilder
StringBuffer 和 StringBuilder 都是可变对象,它们内部使用一个可动态扩展的字符数组来存储字符串内容。StringBuffer 和 StringBuilder 的主要区别在于线程安全性,它们的内部实现基本相同,以 StringBuilder 为例,其内部字符数组定义如下:
char[] value;
当对 StringBuffer 或 StringBuilder 对象进行修改操作时,会直接在原对象的字符数组上进行修改,不会创建新的对象,除非字符数组的容量不够,需要进行扩容。
2. 性能比较
String
由于 String 是不可变对象,每次修改都会创建新的对象,这会导致频繁的内存分配和垃圾回收,尤其是在进行大量字符串拼接操作时,性能会受到严重影响。例如,下面的代码在循环中进行字符串拼接:
long startTime = System.currentTimeMillis();
String result = "";
for (int i = 0; i < 10000; i++) {result = result + i;
}
long endTime = System.currentTimeMillis();
System.out.println("String 拼接耗时: " + (endTime - startTime) + " 毫秒");
在这个循环中,每次拼接都会创建一个新的 String 对象,会产生大量的临时对象,导致性能较低。
StringBuffer 和 StringBuilder
StringBuffer 和 StringBuilder 由于是可变对象,在进行字符串拼接等修改操作时,直接在原对象上进行,避免了频繁的内存分配和垃圾回收,性能明显优于 String。例如,使用 StringBuilder 进行同样的拼接操作:
long startTime = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {sb.append(i);
}
String result = sb.toString();
long endTime = System.currentTimeMillis();
System.out.println("StringBuilder 拼接耗时: " + (endTime - startTime) + " 毫秒");
StringBuilder 的 append 方法直接在原对象的字符数组上添加新的字符,性能较高。
性能对比总结
在进行少量字符串操作时,String、StringBuffer 和 StringBuilder 的性能差异不明显;但在进行大量字符串拼接、替换等操作时,StringBuilder 和 StringBuffer 的性能远高于 String,而 StringBuilder 的性能又略高于 StringBuffer。
3. 线程安全性
String
由于 String 是不可变对象,一旦创建就不能被修改,所以不存在线程安全问题。多个线程可以同时访问同一个 String 对象,不会出现数据不一致的情况。
StringBuffer
StringBuffer 是线程安全的,它的所有公共方法都使用了 synchronized 关键字进行同步,保证了在多线程环境下操作的安全性。例如,StringBuffer 的 append 方法定义如下:
@Override
public synchronized StringBuffer append(String str) {toStringCache = null;super.append(str);return this;
}
在多线程环境下,如果多个线程同时对 StringBuffer 对象进行修改操作,会自动进行同步,避免数据不一致的问题。
StringBuilder
StringBuilder 是非线程安全的,它的方法没有使用 synchronized 关键字进行同步。因此,在多线程环境下,如果多个线程同时对 StringBuilder 对象进行修改操作,可能会出现数据不一致的情况。但在单线程环境下,由于不需要进行同步操作,StringBuilder 的性能会略高于 StringBuffer。
4. 使用场景
String
- 当字符串内容不需要频繁修改,且使用频率较高时,建议使用
String。例如,存储一些常量字符串、配置信息等。 - 在需要对字符串进行比较操作时,
String提供了丰富的比较方法,使用起来更加方便。
StringBuffer
- 在多线程环境下,需要对字符串进行频繁修改操作时,应使用
StringBuffer。例如,在多线程的日志记录系统中,多个线程可能同时向日志字符串中添加信息,此时使用StringBuffer可以保证线程安全。
StringBuilder
- 在单线程环境下,需要对字符串进行频繁修改操作时,应优先使用
StringBuilder。例如,在进行字符串拼接、格式化等操作时,StringBuilder可以提供更好的性能。
总结
String、StringBuffer 和 StringBuilder 各有特点,在不同的场景下应根据实际需求进行选择。String 适用于字符串内容不需要频繁修改的场景;StringBuffer 适用于多线程环境下的字符串修改操作;StringBuilder 适用于单线程环境下的字符串修改操作。正确选择合适的字符串处理类,可以提高代码的性能和效率。
相关文章:
String、StringBuffer、StringBuilder 区别
在 Java 编程中,String、StringBuffer 和 StringBuilder 是处理字符串时常用的类。它们在功能上有相似之处,但在内部实现、性能、线程安全性等方面存在显著差异。理解这些差异有助于开发者在不同的场景下做出合适的选择,提高代码的性能和效率…...
shell——分支语句
文章目录 基本语法常用判断条件(1)两个整数之间比较(2)按照文件权限进行判断(3)按照文件类型进行判断(4)多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令…...
【vue3】实现pdf在线预览的几种方式
今天一天对当前可用的pdf预览插件做了测试,主要需求是只能预览不能下载,但对于前端来说,没有绝对的禁止,这里只罗列实现方式。 目前采用vue3版本为:3.2.37 iframevue-officepdfjs-dist iframe 先说最简单的…...
(学习总结22)Linux 基本指令1
Linux 基本指令1 基本指令当前目录信息指令 ls查看路径指令 pwd改变当前所在目录指令 cd创建或更改文件时间指令 touch创建目录指令 mkdir删除空目录指令 rmdir删除指令 rm查阅手册指令 man拷贝文件指令 cp移动文件指令 mv打印内容指令 echo 查看指令查找文件指令 find查看指令…...
Linux:用 clang 编译带 sched_ext 功能内核
文章目录 1. 前言2. 编译过程2.1 准备内核源代码2.2 安装编译工具2.3 配置、编译、运行2.3.1 配置2.3.2 编译2.3.3 运行 3. 参考资料 1. 前言 限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。 2. 编译过程 …...
Redis 的集群 --- 数据分开扛
序言 上一章内容中我们介绍到了 哨兵 来保证我们主机在发生故障时能够及时地选出一个新的主机,但是哨兵地加入只是提供了 高可用性 和 故障转移,并没有真正的提升架构的性能。如果不断地加入新的数据的话,主机的压力会很大,一方面…...
微信小程序中缓存数据全方位解惑
微信小程序中缓存数据全方位解惑 微信小程序中的数据缓存是提升用户体验和优化性能的重要手段,跟电脑浏览器中的Local Storage的性质一样。以下是关于微信小程序数据缓存的相关知识点和示例的详细介绍: 1. 数据缓存的类型 微信小程序提供了两种数据缓…...
LeetCode 每日一题 2025/2/10-2025/2/16
记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步 目录 2/10 913. 猫和老鼠2/11 1728. 猫和老鼠 II2/12 1760. 袋子里最少数目的球2/13 1742. 盒子中小球的最大数量2/14 1552. 两球之间的磁力2/15 1706. 球会落何处2/16 1299. 将…...
使用 Shiro 和 JPA 结合 MySQL 实现一个简易权限管理系统
1. 项目设置 首先,确保你的项目已经配置好 Maven 或 Gradle 依赖管理工具,并添加以下依赖: Maven 依赖 <dependencies><!-- Shiro 核心库 --><dependency><groupId>org.apache.shiro</groupId><artifactI…...
DeepSeek与医院电子病历的深度融合路径:本地化和上云差异化分析
一、引言 1.1 研究背景与意义 在医疗信息化快速发展的当下,电子病历系统已成为医院信息管理的核心构成。电子病历(EMR)系统,是指医务人员在医疗活动过程中,使用医疗机构信息系统生成的文字、符号、图标、图形、数据、影像等数字化信息,并能实现存储、管理、传输和重现的…...
设计模式:代理模式
代理模式是很常见的设计模式,即使没有专门学习过这种设计模式,在工作中也一定用过这种设计模式。在实际生活中,代理模式也是常见的,比如内阁首辅相对于皇帝,前者是后者的代理,内阁首辅收到奏折时࿰…...
141,【1】buuctf web [SUCTF 2019]EasyWeb
进入靶场 代码审计 <?php // 定义函数get_the_flag,功能是处理文件上传相关操作 function get_the_flag() {// 注释说明:webadmin会每隔20分钟删除用户上传的文件$userdir "upload/tmp_" . md5($_SERVER[REMOTE_ADDR]);// 检查用户目录…...
破解微服务疑难杂症:2025年全解决方案
微服务架构已经成为现代软件开发的主流选择,其优势在于能够将复杂的系统拆分为独立的服务模块,方便开发和维护。然而,在微服务的实施过程中,开发者往往会面临许多挑战,如服务间通信、数据一致性、性能优化和故障处理等…...
Node.js 中的 Event 模块详解
Node.js 中的 Event 模块是实现事件驱动编程的核心模块。它基于观察者模式,允许对象(称为“事件发射器”)发布事件,而其他对象(称为“事件监听器”)可以订阅并响应这些事件。这种模式非常适合处理异步操作和…...
EasyRTC嵌入式WebRTC视频通话SDK支持Web浏览器、Linux、ARM、Android、iOS
随着互联网技术的飞速发展,实时通信(RTC)已经成为现代应用中不可或缺的一部分。无论是视频会议、在线教育、远程医疗,还是社交娱乐,实时通信技术都在其中扮演着重要角色。 然而,WebRTC技术在PC和移动端的支…...
pycharm社区版有个window和arm64版本,到底下载哪一个?还有pycharm官网
首先pycharm官网是这一个。我是在2025年2月16日9:57进入的网站。如果网站还没有更新的话,那么就往下滑一下找到 community Edition,这个就是社区版了免费的。PyCharm:适用于数据科学和 Web 开发的 Python IDE 适用于数据科学和 Web 开发的 Python IDE&am…...
【玩转全栈】----Django模板语法、请求与响应
目录 一、引言 二、模板语法 三、传参 1、视图函数到模板文件 2、模板文件到视图函数 四、引入静态文件 五、请求与响应 ?1、请求 2、响应 六、综合小案例 1、源码展示 2、注意事项以及部分解释 3、展示 一、引言 像之前那个页面,太过简陋,而且一个完整…...
网络安全:挑战、技术与未来发展
📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 1. 引言 在数字化时代,网络安全(Cybersecurity)已成为全球关注的焦点。随着云计算、大数据、…...
DeepSeek 服务器繁忙的全面解决方案
目录 引文 正文 一、 服务器繁忙的原因分析 二、 解决方案 2.1切换网络 2.2使用网络加速工具 2.3错峰使用DeepSeek 2.4本地部署 2.5调用API 三、官方动态 一、技术研发与产品升级 二、市场合作与商业化进展 三、区域化布局与产业赋能 四、未来规划与社会责任 结语…...
将OpenWrt部署在x86服务器上
正文共:1234 字 40 图,预估阅读时间:2 分钟 如果你问ChatGPT有哪些开源的SD-WAN方案,他会这样答复你: 我们看到,OpenWrt也属于比较知名的开源SD-WAN解决方案。当然,在很久之前,我就发…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果