Java面试要点03 - String、StringBuilder与StringBuffer全面对比

在这里插入图片描述

本文目录

    • 一、引言
    • 二、String的特性与实现原理
    • 三、StringBuilder的工作机制
    • 四、StringBuffer的同步机制
    • 五、性能对比与分析
    • 六、最佳实践与应用场景
    • 七、总结


一、引言

在Java中,字符串操作是最常见的编程任务之一。Java提供了三种主要的字符串处理类:String、StringBuilder和StringBuffer。虽然它们都用于处理字符串,但在实现原理、性能特性和使用场景上存在显著差异。深入理解这些差异,对于编写高效的Java程序至关重要。

二、String的特性与实现原理

String类是Java中最基础的字符串类型,它的最显著特点是不可变性(Immutable)。当我们创建一个String对象后,其内容是不可改变的。这种不可变性是通过内部的私有final字符数组实现的。在Java 9之后,为了优化性能和内存占用,String内部改用了私有final字节数组,并增加了一个编码标记字段。

public class StringPrinciple {public static void main(String[] args) {String str = "Hello";String newStr = str + " World";  // 创建新对象System.out.println("str hashCode: " + System.identityHashCode(str));System.out.println("newStr hashCode: " + System.identityHashCode(newStr));// String常量池演示String s1 = "hello";  // 字面量,存入常量池String s2 = "hello";  // 复用常量池中的对象String s3 = new String("hello");  // 在堆中创建新对象System.out.println("s1 == s2: " + (s1 == s2));  // trueSystem.out.println("s1 == s3: " + (s1 == s3));  // falseSystem.out.println("s1.equals(s3): " + s1.equals(s3));  // true}
}

String类的不可变性带来了诸多优势:它天然是线程安全的,可以安全地在多个线程间共享;它的hashCode可以被缓存,提高在散列表中的性能;它可以实现字符串常量池的优化。但是,这种不可变性也意味着,每次字符串运算都会创建新的String对象,在进行频繁的字符串操作时可能会带来性能问题。

三、StringBuilder的工作机制

StringBuilder是可变的字符序列,它在内部维护了一个可变的字符数组。与String不同,StringBuilder的操作都会直接修改这个字符数组,而不是创建新的对象。这使得StringBuilder在进行字符串操作时具有更高的性能。

public class StringBuilderMechanism {public static void main(String[] args) {StringBuilder builder = new StringBuilder("Hello");System.out.println("Initial capacity: " + builder.capacity());// 直接修改底层数组builder.append(" World");System.out.println("Modified string: " + builder.toString());// 演示扩容机制StringBuilder sb = new StringBuilder(5);String padding = "abcde";for (int i = 0; i < 3; i++) {System.out.println("Current capacity: " + sb.capacity());sb.append(padding);}// 常用操作演示StringBuilder operation = new StringBuilder("Hello World");operation.insert(5, " Java");  // 插入operation.delete(5, 10);      // 删除operation.reverse();          // 反转operation.replace(0, 5, "Hi"); // 替换}
}

StringBuilder的优势在于它的可变性和非同步性。当我们需要在单线程环境下频繁修改字符串时,StringBuilder是最佳选择。它的操作方法都是非线程安全的,但正是因为没有同步开销,所以性能最好。

四、StringBuffer的同步机制

StringBuffer是StringBuilder的线程安全版本。它的所有公开方法都是同步的,使用synchronized关键字修饰,这保证了在多线程环境下的安全性。

public class StringBufferSynchronization {private static final StringBuffer SHARED_BUFFER = new StringBuffer();public static void main(String[] args) throws InterruptedException {// 创建多个线程同时操作StringBufferRunnable task = () -> {for (int i = 0; i < 1000; i++) {SHARED_BUFFER.append("a");try {Thread.sleep(1);  // 增加线程切换的机会} catch (InterruptedException e) {Thread.currentThread().interrupt();}}};Thread t1 = new Thread(task);Thread t2 = new Thread(task);t1.start();t2.start();t1.join();t2.join();System.out.println("Final length: " + SHARED_BUFFER.length());// 输出为2000,证明线程安全}
}

虽然StringBuffer提供了线程安全保证,但这种安全性是以性能为代价的。每次调用方法都要获取锁,这在单线程环境下会造成不必要的性能开销。因此,如果不需要线程安全特性,应该优先使用StringBuilder。

五、性能对比与分析

通过一个详细的性能测试来比较这三个类在不同场景下的表现:

public class PerformanceComparison {public static void main(String[] args) {int iterations = 100000;// 测试String连接性能long startTime = System.nanoTime();String str = "";for (int i = 0; i < iterations; i++) {str += "a";}long stringTime = System.nanoTime() - startTime;// 测试StringBuilder性能startTime = System.nanoTime();StringBuilder builder = new StringBuilder();for (int i = 0; i < iterations; i++) {builder.append("a");}long builderTime = System.nanoTime() - startTime;// 测试StringBuffer性能startTime = System.nanoTime();StringBuffer buffer = new StringBuffer();for (int i = 0; i < iterations; i++) {buffer.append("a");}long bufferTime = System.nanoTime() - startTime;// 输出性能对比结果System.out.printf("String时间:%d ms%n", stringTime / 1000000);System.out.printf("StringBuilder时间:%d ms%n", builderTime / 1000000);System.out.printf("StringBuffer时间:%d ms%n", bufferTime / 1000000);// 测试内存使用情况Runtime runtime = Runtime.getRuntime();System.gc();long initialMemory = runtime.totalMemory() - runtime.freeMemory();// 分别测试三种类型的内存占用// ...内存使用测试代码}
}

从性能测试结果可以看出,在进行大量字符串操作时,StringBuilder的性能最好,其次是StringBuffer,最后是String。这是因为String的不可变性导致每次操作都会创建新对象,而StringBuilder和StringBuffer只是修改现有对象的内容。

在内存使用方面,String的操作会产生大量临时对象,导致更多的垃圾回收开销。

六、最佳实践与应用场景

在实际开发中,应该根据具体场景选择合适的字符串处理类。在处理字符串常量时,应该使用String,因为其不可变性提供了安全性保证。在单线程环境下进行字符串操作时,应该使用StringBuilder,因为它提供了最好的性能。在多线程环境下共享字符串缓冲区时,应该使用StringBuffer,以确保线程安全。

public class StringBestPractice {// 常量定义,使用Stringprivate static final String CONSTANT = "这是一个常量";// 单线程字符串处理public String buildReport(List<String> data) {StringBuilder report = new StringBuilder(data.size() * 50);  // 预估容量for (String item : data) {report.append(item).append("\n");}return report.toString();}// 多线程共享的日志缓冲区private static final StringBuffer LOG_BUFFER = new StringBuffer();public void appendLog(String logEntry) {synchronized (LOG_BUFFER) {LOG_BUFFER.append(logEntry).append("\n");}}
}

七、总结

通过深入理解String、StringBuilder和StringBuffer的特性,我们可以在开发中做出更好的选择。String的不可变性使其适合作为常量和安全性要求高的场景;StringBuilder的高性能使其成为单线程字符串操作的首选;而StringBuffer的同步特性则使其适用于多线程环境。在实际应用中,应该根据具体需求,权衡性能和安全性,选择最合适的字符串处理类。

今天的内容就到这里了,希望可以对你有帮助。

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

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

相关文章

【HCIP园区网综合拓扑实验】配置步骤与详解(已施工完毕)

一、实验要求 实验拓扑图如上图所示 1、按照图示的VLAN及IP地址需求&#xff0c;完成相关配置 2、要求SW1为VLAN 2/3的主根及主网关 SW2为vlan 20/30的主根及主网关 SW1和SW2互为备份 3、可以使用super vlan&#xff08;本实验未使用&#xff09; 4、上层…

高铁站网约车智能出行如何实现快速调度功能

在现代交通体系中&#xff0c;高铁站作为重要的交通枢纽&#xff0c;其出行效率和服务质量直接影响乘客的出行体验。随着科技的进步&#xff0c;网约车智能出行已成为高铁站的重要补充&#xff0c;通过高效调度&#xff0c;为乘客提供更加便捷、快速的出行服务。接下来我们一起…

VUE3实现好看的通用网站源码模板

文章目录 1.设计来源1.1 网站主界面1.2 登录界面1.3 注册界面1.4 图文列表模板界面1.5 简洁列表模板界面1.6 文章内容左右侧模板界面1.7 文章内容模板界面 2.效果和源码2.1 动态效果2.2 源代码2.3 目录结构 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff…

【论文笔记】Prefix-Tuning: Optimizing Continuous Prompts for Generation

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: Prefix-Tuning: Optimizin…

大数据机器学习算法与计算机视觉应用04:多项式

The Algorithm Magic of Polynomial PolynomialsThe Root of PolynomialA Delete ChannelPolynomials for Finding Maximum Matchings Polynomials 多项式 一个 d d d 次多项式可以用一个 d 1 d1 d1 元组 c i {c_i} ci​ 表达。在这种情况下&#xff0c;两个多项式相加的…

万字长文解读深度学习——生成对抗网络GAN

&#x1f33a;历史文章列表&#x1f33a; 深度学习——优化算法、激活函数、归一化、正则化深度学习——权重初始化、评估指标、梯度消失和梯度爆炸深度学习——前向传播与反向传播、神经网络&#xff08;前馈神经网络与反馈神经网络&#xff09;、常见算法概要汇总万字长文解读…

万字长文解读深度学习——训练(DeepSpeed、Accelerate)、优化(蒸馏、剪枝、量化)、部署细节

&#x1f33a;历史文章列表&#x1f33a; 深度学习——优化算法、激活函数、归一化、正则化深度学习——权重初始化、评估指标、梯度消失和梯度爆炸深度学习——前向传播与反向传播、神经网络&#xff08;前馈神经网络与反馈神经网络&#xff09;、常见算法概要汇总万字长文解读…

简易入手《SOM神经网络》的本质与原理

原创文章&#xff0c;转载请说明来自《老饼讲解神经网络》:www.bbbdata.com 关于《老饼讲解神经网络》&#xff1a; 本网结构化讲解神经网络的知识&#xff0c;原理和代码。 重现matlab神经网络工具箱的算法&#xff0c;是学习神经网络的好助手。 目录 一、入门原理解说 01.…

Python爬虫快速获取JD商品详情:代码示例与技巧解析

在当今这个信息爆炸的时代&#xff0c;数据成为了一种宝贵的资源。对于电商行业来说&#xff0c;获取商品详情信息是进行市场分析、价格比较、库存管理等重要环节的基础。本文将通过一个Python爬虫示例&#xff0c;展示如何快速获取&#xff08;JD&#xff09;商品的详情信息。…

大数据-218 Prometheus 插件 exporter 与 pushgateway 配置使用 监控服务 使用场景

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

【数字图像处理+MATLAB】将图像转换为二值图像(Binary Image):使用 imbinarize 函数进行二值化运算(Binarize)

引言 二值图像是一种特殊类型的数字图像&#xff0c;其中每个像素只有两种可能的强度值或颜色值。这两种值通常表示为黑色和白色&#xff0c;或者0和1。 二值化是一个常见的图像处理步骤&#xff0c;它将灰度或彩色图像转换为二值图像。在二值化过程中&#xff0c;会设定一个…

智能电销机器人的操作流程

对于电销行业的人来说&#xff0c;有了智能电销机器人&#xff0c;简直是太省心了&#xff01; 智能外呼机器人&#xff0c;是一款基于人工智能语音外呼系统&#xff0c; 它可以代替人工自动拨打电话&#xff0c;自动筛选客户&#xff0c;自动推送意向客户到你的微信上 &#x…

CSDN做样板,教我们如何为新网站引流

CSDN为我们做了个很好的例子&#xff0c;详细请看下图 亮点分析&#xff1a; 1. 未采用硬广在网站上进行引流。减少了给用户在直觉上的造成的反感&#xff1b; 2. 在GitHub的转跳页面中&#xff0c;植入额外的关联网站链接。虽然对用户解决问题没啥鸟用&#xff0c;但是人家能…

电脑局域网内让其他电脑通过IP访问配置

依次点击桌面左下角“开始菜单”>“所有应用”>“Windows系统”>“控制面板”&#xff0c;如图所示 在控制面板界面&#xff0c;选择“查看方式”为“大图标”&#xff0c;然后点击打开window防火墙&#xff0c;如图所示 然后点击“高级设置”&#xff0c;如图所示 在…

网络安全——下载并在kali虚拟机上启动Cobalt Strike

目录 一、下载 二、上传文件到kali虚拟机 三、启动服务端 四、启动客户端 一、下载 CobaltStrike4.8汉化版带插件-CSDN博客 下载并解压后 二、上传文件到kali虚拟机 1、打开并运行kali虚拟机&#xff0c;查看kali的ip地址 2、打开xshell&#xff0c;新建连接&#xff0c;连…

[Win11]集成化综合漏洞扫描系统[更新]

前言 之前是为了方便外包仔在客户现场漏扫所以才集成的这个系统 优点&#xff1a;倒腾一下格式可以直接在客户的Vmware ESXI上面上面部署&#xff0c;同时个人版Vmware也可以拿来直接用。 由Linux版本改为了Windows版(有很多不会用) 因为前两个更新的很频繁&#xff0c;所以…

【SSL-RL】自监督强化学习:随机潜在演员评论家 (SLAC)算法

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…

详解MySQL安装

目录 Ubantu 1. 使⽤apt安装MySQL 2.查看MySQL状态 3. MySQL 安装安全设置 4.设置密码 卸载MySQL Centos 1. 确认当前的系统版本 2.下载MySQL源 3.安装MySQL 4.启动mysqld 5.查看MySQL状态 6.设置开机自启动 7.查看MySQL密码&#xff0c;并登录 8.修改密码 Ubant…

【MATLAB源码-第213期】基于matlab的16QAM调制解调系统软硬判决对比仿真,输出误码率曲线对比图。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 一、16QAM调制原理 在16QAM&#xff08;16 Quadrature Amplitude Modulation&#xff09;调制中&#xff0c;一个符号表示4个比特的数据。这种调制方式结合了幅度调制和相位调制&#xff0c;能够在相同的频谱资源下传输更多的…

Renesas R7FA8D1BH (Cortex®-M85) Data Flash程序功能实现

目录 概述 1 Data Flash空间 2 FSP配置参数 3 源代码介绍 3.1 源代码 3.2 中断函数 3.3 源代码文件 4 测试 4.1 测试实现 4.2 测试 概述 本文主要介绍使用FSP提供的库函数操作Renesas R7FA8D1BH (Cortex-M85) Data Flash的方法&#xff0c;笔者使用FSP配置参数&#x…