String类的学习笔记(下):字符串拼接以及StringBuilder和StringBuffer的学习

news2025/1/22 21:34:27

本文介绍了String类对字符串进行拼接的方法 和拼接字符串的效率分析 以及能对字符串内容进行修改的StringBuilder和StringBuffer类其常用方法和区别 , 最后介绍了两个字符串经典面试题

StringBuilder和StringBuffer的学习

  • 一.String类概括
  • 二.StringBuilder和StringBuffer
    • 1.字符串拼接
    • 2.StringBuilder和StringBuffer常用方法和区别
    • 3. 面试题:以下代码共创建多少个对象?
    • 4.面试题: String 、StringBuilder和StringBuffer的异同
  • 三.总结

一.String类概括

1.String常用方法学习->2.String的不可变和字符串常量池->StringBuilder和StringBuffer

String类是Java中用来描述操作字符串的类
上两篇博客介绍了介绍了常用的方法,以及String的特性:String内容是不可变的以及字符串常量池,感兴趣的可以去看看…

二.StringBuilder和StringBuffer

StringBulder和StringBuffer是和String一样都是对字符串进行操作的类
而学了String后知道,String内容是不可变的,对String的内容进行修改都会创建一个新的字符串返回

而创建新的String对象比原字符串修改所耗费的时间空间更多,效率低很多

因此,java中提供的StringBuilder和StringBuffer是专门用来对字符串进行原地修改的类,并且它们都可以和String类之间进行相互转换

在这里插入图片描述
在这里插入图片描述
通过源码看到 这两个类的方法大致都相同,且都extends继承了AbstractStringBuilder类

在这里插入图片描述
而AbstractStringBuilder类 底层是存在一个value 数组引用和count变量的,其没有被private和final修饰 能够在StringBuilder和StringBuffer中访问到

value数组即维护的是字符串内容 , 而count记录的是value内有效的字符个数即真正的字符串长度

(因为value指向的字符数组长度是当前存放字符串的空间,还有预留的空间用来新增字符等, count记录的才是字符串真正的长度)

由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大部分功能是相同的

1.字符串拼接

在String方法中提供concat和join方法 可以使字符串之间进行拼接

在这里插入图片描述

concat是成员方法,使一个字符串对象内容与另一个字符串对象进行连接成一个新的字符串对象返回
在这里插入图片描述

join是静态成员方法, 方法第一个参数 是连接的分隔字符串, 后续2~n个是用来连接的字符串, 会将其拼接在一起 用一个参数做分隔(分隔连接的每段字符串,如果只有一段则不显示分隔符),最后返回此拼接的字符串对象

在这里插入图片描述

但上面这些方法并不具备将其他数据类型的数据拼接进字符串的功能因此使用这些方法还要拼接其他非String类型的数据还要将其先转换为字符串再进行拼接

而在Java中,String类型 用 + 连接 String字符串数据和任意类型数据 都可以使其简单快捷直接拼接为一个新字符串对象
示例:

public static void main(String[] args) {

        System.out.println("12"+3);
        System.out.println(3+"12");
        System.out.println(1+2+"12");
        System.out.println("12"+1+2);
        System.out.println(false+"12"+true);
        //代码输出结果是什么?
    }

在这里插入图片描述
字符串类型数据和任何数据类型数据 之间使用+运算,都可以拼接成一个新的字符串对象,

但注意要运算符的优先级, 1+2+“12” 是先计算1+2 结果为3 再3+“12"拼接成字符串"312”

“12”+1+2,是先"12"+1拼接成字符串"121" 再+2 拼接成字符串"1212"

boolean类型数据可以参与字符串拼接

“”+12 可以使 12数字拼接为字符串"12"

通过+号可以快速实现字符串拼接,这种用法很方便让我们使基本数据类型快速变为字符串类型

StringBuilder和StringBuffer也可以实现字符串拼接, 需要调用其内部的append方法:

public static void main(String[] args) {
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append(1+2);
        stringBuilder.append(12);
        System.out.println(stringBuilder);
        stringBuilder.append(3);
        System.out.println(stringBuilder);
        stringBuilder.append(false);
        System.out.println(stringBuilder);
 }

在这里插入图片描述

可以看到通过StringBuilder对象 使用其append方法可以将任意数据类型拼接成一个字符串
在这里插入图片描述
而append方法内部最后返回的都是StringBuilder对象本身,并没有创建新对象…

从运行效率上String类型使用+和其他数据拼接 和StringBuiler以及的append方法哪种更好?

此时可以使用Java内一种计算内部运行时间的方法System.currentTimeMillis()采取差值运算, 来分别测试这三个的运行时间…
示例:

public static void main(String[] args) {
        long start = System.currentTimeMillis();  // 计算当前内部运行时间
        String s = "";

        for(int i = 0; i < 10000; ++i){
            s += i;                             //字符串类型 加任意基本数据类型 都会拼接成一个新字符串再给s引用接收
        }   // 每+=一次 会额外创建三个对象
        long end = System.currentTimeMillis();
        System.out.println(end - start);
        start = System.currentTimeMillis();
        StringBuffer sbf = new StringBuffer("");  // 需要加锁解锁
        for(int i = 0; i < 10000; ++i){
            sbf.append(i);                     //对字符串内的数组进行操作 不会创建额外字符串
        }
        end = System.currentTimeMillis();
        System.out.println(end - start);
        start = System.currentTimeMillis();
        StringBuilder sbd = new StringBuilder();
        for(int i = 0; i < 10000; ++i){
            sbd.append(i);                 //对字符串内的数组进行操作 不会创建额外字符串
        }
        end = System.currentTimeMillis();
        System.out.println(end - start);
    }

在这里插入图片描述
通过运行结果可大概估计:拼接效率:String<StringBuffer<StringBuilder

为什么String类型使用+进行字符串拼接效率比StringBuilder和StringBuffer慢很多?

通过 javap -c 字节码文件 反汇编此文件, 能看到使用+号底层做了些什么事
在这里插入图片描述
使用+进行拼接, 本质上是先new了一个StringBuilder对象,然后调用append方法将s字符串追加进去,再调用append 将i 追加进去, 最后调用了toString方法返回~

在这里插入图片描述
而StringBuilder重写了toString方法,其作用是 实例一个新String对象,
将StringBuilder继承的AbstractStringBuilder的value数组引用指向的数组 和 ,0 ,count作为参数传参调用其构造方法,

作用是 创建一个String对象 其内容是 value指向的数组对象 0~count之间的内容 (注意:String内的value是指向的新value数组)

可见:使用+号拼接字符串,在底层是使用了StringBuilder对象的append方法,最后返回的也是一个新String对象…

那在上述代码中, 使用for循环通过+号拼接了10000个i, 每次拼接都会创建一个StringBuilder对象和String对象, 可见完成此操作需要new如此多的对象,而且还要回收掉未被指向的String对象, 消耗非常大

而直接实例StringBuilder对象通过append追加字符串内容, 全部追加完成后最后只需要将StringBuilder对象转换String对象 进行一次操作即可, 在此操作里只额外实例化了两个对象, 开销比+号少的多

故:在使用大量字符串追加操作时, 不建议使用+号操作符进行拼接, 其性能远远低于用StringBuilder进行append拼接, 而使用StringBuilder效率比其他拼接方法效率更高

(“1”+“2” 字符串常量用+号拼接不会进行上述append在底层直接看成"12"字符串)

2.StringBuilder和StringBuffer常用方法和区别

StringBuilder和StringBuffer都能对字符串进行修改, 其内部大部分方法也是相同
以下是一些常用的其内能对字符串内容进行修改的方法如:

方法作用
append()在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、double、float、int、long、Object、String、StringBuff的变量
void setCharAt(int index,char ch)将index位置的字符设置为ch
insert(int offset, String str)在offset位置插入:八种基类类型 & String类型 & Object类型数据
deleteCharAt(int index)删除index位置字符
delete(intstart, int end)删除[start, end)区间内的字符
replace(intstart, int end, String str)将[start, end)位置的字符替换为str
reverse()将字符串进原地逆置
toString()将内容以String对象形式返回

以上是StringBulider和StringBuffer常用到的对字符串内容进行修改的方法,其内还有一些和Stirng类一样的方法如 indexOf(),具体可自己去了解

既然大部分方法都是相同的,那这两个类的具体区别在哪?

因为String类不能对字符串进行修改,其设计可以使线程更安全,每个线程对方法的调用都是创建新字符串对象, 而 StringBuilder能对字符串内容进行修改,那就会导致多个线程同时调用一个方法会产生一些问题… 此时正是要解决这个线程不安全的问题

在这里插入图片描述
在这里插入图片描述
通过源码可以看到,StringBuffer内大部分的方法都有synchronized(同步) 关键字修饰 ,被此关键字修饰的方法即为同步方法, 其是线程安全的, 表示在多线程情况下, 不同线程同时调用这个方法时会将其上锁,同一时间只能有一个线程执行此方法,其它线程只能等待执行完这个方法解锁后才能一一执行此方法

而在上面StringBuffer 和StringBuilder 对象 对10000个i进行拼接时, StringBuilder比其效率高一点,也是因为 StringBuffer 执行方法时 还要 进行加锁解锁操作,此也是要消耗资源的…

故StringBuffer类用在多线程情况下,对字符串对象进行修改 而StringBuilder用在单线程情况下

3. 面试题:以下代码共创建多少个对象?

 public static void main(String[] args) {

        String str=new String("123");  // 创建多少个对象
        String str1=new String("1"+"2")+new String("3"); //创建多少个对象
//以上程序在运行时字符串常量都是第一次出现字符串常量池并不存在程序中的常量字符串
    }

在程序运行时,并 str代码 一个"123"对象并存放在字符串常量池里,new String()一个对象; 最后 创建了两个String对象

str1处 首先new了一个StringBuilder对象 再 new String() 一个对象 , “1”+“2” 底层直接编程成"12" 是一个String对象 , 再被拼接到StringBuilder中, 然后在new String对象, 然后"3"一个对象 , 再被拼接到StringBuilder对象中 , 最后 StringBuilder调用了toString又new了一个String对象 返回 , 最后 new了1个StringBuilder对象和五个String对象

注意str1最后接受的字符串内容是123 但是其和字符串常量池中的"123" 是不同的
字符串常量池是在编译时将其字符串常量"123"存放进去的, 而str1接受的是后续拼接出来的字符串123

在这里插入图片描述

4.面试题: String 、StringBuilder和StringBuffer的异同

三者都是用来描述操作字符串的类

String类的内容是不可变的所有对String内容进行修改的操作都是创建新String对象

,StringBuilder和StringBuffer的内容都是可变的,常用来对字符串内容进行频繁修改时使用,

StringBuffer与StringBuilder大部分功能是相似的

StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作

三.总结

本文介绍了字符串拼接的方法 (String的成员方法concat和类成员方法join +号运算符拼接 StringBuilder和StringBuffer的append拼接 )以及各种拼接方法的效率 和底层反汇编分析, StringBuffer和StringBuilder的大部分对内容进行修改的方法,和其不同点, 以及两大字符串方面的面试题 及其分析

在这里插入图片描述

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

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

相关文章

是未来的超级计算机还是只是一场炒作?

随着科技的飞速发展和创新&#xff0c;量子计算技术逐渐成为了人们关注的热点话题。量子计算作为一种前沿的计算方式&#xff0c;具有超强的运算能力和突破性的创新潜力&#xff0c;因此备受瞩目。然而&#xff0c;随着各大公司和机构纷纷加入到这一领域的竞争中&#xff0c;一…

超详细github配置(仔细看,看完不会,你怪我)

github的重要性&#xff1a; 网络时代的程序员必备。 github的作用&#xff1a; 版本管理多人协作开源共享 常用方案&#xff1a; gitTortoiseGitgithub [Tortoise&#xff0c;程序员常称其为小乌龟&#xff0c;小海龟] 安装配置步骤 1.注册 GitHub: Where the world bu…

服务(第二十二篇)主从复制和读写分离

主从复制原理&#xff1a; 首先主节点会开启二进制日志&#xff0c;从节点会开启中继日志&#xff0c;从节点会开启io线程检测主节点是否有更新&#xff0c;如果更新了就会向主节点请求二进制事件&#xff0c;主会开启dump线程发送二进制事件&#xff0c;然后保存在从节点的中…

假如面试官让你十分钟完成双向循环链表

&#x1f48c; 博客内容&#xff1a;假如面试官让你十分钟完成双向循环链表&#xff0c;多一秒都不行 &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准前端&#xff0c;专注基础和实战分享 &#xff0c;欢迎私信&…

大前端技能讲解:NodeJS、Npm、Es6、Webpack

文章目录 1. 基础概述2. Nodejs2.1 Nodejs 了解和快速入门2.2 Nodejs 实现 Httpserver 服务&#xff08;实现请求响应&#xff09;2.3 Nodejs 操作 MySQL 数据库 3. ES63.1 ES6 的概述3.2 ES6 的语法&#xff1a;let 和 const 命令3.3 ES6 的语法&#xff1a;模板字符串3.4 ES6…

基于SSM的在线电影购票系统设计与实现【附源码】

基于SSM的在线电影购票系统设计与实现 互联网的不断迅猛发展&#xff0c;每个行业都在寻找新的机会&#xff0c;都在从传统的人工方式向先进的信息化过度。随着人民生活水平的提高伴随的精神文化层次的享受&#xff0c;而现代互联网时代人们的重要精神消费之一是电影行业&…

NAS +AList实现云盘映射(本地硬盘扩容大法)

准备工具&#xff1a; 1&#xff09;Alist的docker &#xff1a;xhofe/alist 2&#xff09;RailDrive软件 安装&#xff1a; 1&#xff09;安装alist的docker 注意一定要给读写权限&#xff0c;装载路径和我一样 端口一般和容器端口一致 环境变量 网络桥接就行 记得勾选自…

【Prompting】ChatGPT Prompt Engineering开发指南(1)

ChatGPT Prompt Engineering开发指南1 Prompting指南设置 提示原则策略1&#xff1a;使用分隔符清楚地指示输入的不同部分策略2&#xff1a;要求结构化输出策略3&#xff1a;让模型检查条件是否满足策略4: “Few-shot”提示 原则2&#xff1a;给模型时间“思考”策略1&#xff…

idea新建springboot项目并提交码云仓库

新建springboot项目 平常我们在使用联网方式新建springboot项目时总是会遇到连接失败等这种情况 IDEA创建项目&#xff0c;本质是从官网创建并下载项目&#xff0c;然后导入本地。 创建项目连接失败&#xff0c;一般是外国网站的原因导致连接超时&#xff0c;解决方式很简单&a…

C++linux高并发服务器项目实践 day11

Clinux高并发服务器项目实践 day11 线程同步互斥锁死锁读写锁读写锁相关操作函数 生产者消费者模型条件变量信号量 线程同步 线程的主要优势在于&#xff0c;能够通过全局变量来共享信息。不过&#xff0c;这种便捷的共享是有代价的:必须确保多个线程不会同时修改同一变量&…

LabVIEWCompactRIO 开发指南17 网络流

LabVIEWCompactRIO 开发指南17 网络流 网络流类似于队列函数&#xff0c;因为它们是基于FIFO的&#xff0c;但与队列函数不同的是&#xff0c;网络流具有网络作用域。它们是为通过以太网进行无损、高吞吐量数据通信而设计和优化的&#xff0c;并且它们具有增强的连接管理功能…

Springboot +Flowable,各种历史信息如何查询(三)

一.简介 正在执行的流程信息是保存在以 ACT_RU_ 为前缀的表中&#xff0c;执行完毕的流程信息则保存在以 ACT_HI_ 为前缀的表中&#xff0c;也就是流程历史信息表。 假设有一个流程&#xff0c;流程图如下&#xff1a; 当这个流程执行完毕后&#xff0c;以 ACT_RU_ 为前缀的…

学习新技术,争做新青年:请ChatGPT帮我写一篇计算机视觉分类算法论文

文章目录 学习新技术&#xff0c;争做新青年&#xff1a;你不会还不用 ChatGPT 吧&#xff1f;学习新技术请告诉我最好的图像分类模型是哪个请推荐最新的分类模型是哪个请详细介绍一下 Swin Transformer请给出Swin Transformer的论文链接请帮我分析一下Swin Transformer 的创新…

Java实现多线程操作多账户

前言 某公司一个面试题&#xff1a; 1.有二十个账户&#xff0c;每个账户初始余额10000元。 2.有十个转账线程&#xff0c;对二十个账户中的两个随机选取账户进行转账&#xff0c;转账额度100以内正整数随机数。 3.每个线程执行100次转账操作。 4.最后请打印出二十个账户的…

西门子PLC控制步进电机方法与接线(全)

一、步进驱动系统 步进驱动系统包含步进电动机和步进驱动器&#xff0c;前端由PLC发脉冲。 步进电机是将电脉冲信号转变为角位移或线位移以控制转子转动的开环控制电机&#xff08;可以通过安装编码器形成闭环系统&#xff09;。 它旋转是以固定的角度&#xff08;步距角&…

ThinkPHP6的控制器定义及控制器初使用

ThinkPHP6的控制器定义及控制器初使用 控制器定义 控制器文件通常放在controller下面&#xff0c;类名和文件名保持大小写一致&#xff0c;并采用驼峰命名&#xff08;首字母大写&#xff09;。 如果要改变controller目录名&#xff0c;需要在route.php(config/route.php)配…

redis从零开始(1)----五种基本类型:string/hash

认识redis NoSQL Nosql not only sql&#xff0c;泛指非关系型数据库&#xff0c;与之相对的是RDBMS(Relational Database Management System)&#xff0c;即关系型数据库 关系型数据库&#xff1a;列行&#xff0c;同一个表下数据的结构是一样的。 非关系型数据库&#xff…

原生js手动实现一个多级菜单效果(高度可过渡变化)

文章目录 学习链接效果图代码要点 学习链接 vue实现折叠展开收缩动画 - 自己的链接 elment-ui/plus不定高度容器收缩折叠动画组件 - 自己的链接 Vue transition 折叠类动画自动获取隐藏层高度以及手风琴效果实现 vue transition动画钩子- vue官网 vue transition 过渡动画…

vue基础入门

1. vue简介 1.1 什么是vue 官方概念&#xff1a;Vue&#xff08;读音/vju:/&#xff0c;类似于view&#xff09;是一套用于构建用户界面的前端框架 1.2 vue 的特性 vue 框架的特性&#xff0c;主要体现在如下两方面&#xff1a; ① 数据驱动视图 ② 双向数据绑定 数据驱动…

IMS补充业务场景介绍

呼叫保持流程 通话主动Hold的一方,发INVITE消息,媒体流从sendrecv变为sendonly,对方返回200 ok,媒体流从sendrecv变为recvonly,双方ACK后,进入呼叫保持状态,没有通话的RTP包。 大致流程如下 UE A发送INVITE(Sendonly)到网络 网络发送INVITE(Sendonly)到UE B UE发…