Java基础-String Class(字符串类)
String
Java String 类概览
String 类是 Java 中最常用的类之一,用于处理字符串。以下是 String 类的主要特性和操作:
特性/操作 | 描述 |
---|---|
不可变性 | String 对象一旦创建就不能被修改 |
创建方式 | 使用双引号 “” 或 String 构造函数 |
字符串池 | Java 维护字符串常量池以优化内存使用 |
比较操作 | equals() 比较内容,compareTo() 比较顺序 |
连接操作 | 使用 + 运算符或 concat() 方法 |
String的常用Method
方法 | 描述 | 示例 |
---|---|---|
length() | 返回字符串的长度 | "Hello".length() 返回 5 |
charAt(int index) | 返回指定索引处的字符 | "Java".charAt(0) 返回 ‘J’ |
substring(int beginIndex, int endIndex) | 返回一个新的字符串,它是此字符串的一个子字符串 | "Hello".substring(0, 3) 返回 “Hel” |
equals(Object anObject) | 将此字符串与指定的对象比较 | "Hello".equals("Hello") 返回 true |
toLowerCase() | 使用默认语言环境的规则将此 String 中的所有字符都转换为小写 | "HELLO".toLowerCase() 返回 “hello” |
toUpperCase() | 使用默认语言环境的规则将此 String 中的所有字符都转换为大写 | "hello".toUpperCase() 返回 “HELLO” |
trim() | 返回字符串的副本,忽略前导空白和尾部空白 | " hello ".trim() 返回 “hello” |
replace(char oldChar, char newChar) | 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的 | "hello".replace('l', 'w') 返回 “hewwo” |
contains(CharSequence s) | 当且仅当此字符串包含指定的 char 值序列时,返回 true | "Hello".contains("He") 返回 true |
split(String regex) | 根据给定正则表达式的匹配拆分此字符串 | "a,b,c".split(",") 返回 [“a”, “b”, “c”] |
下面的流程图展示了 String 对象的生命周期和常见操作:
这个流程图说明了 String 对象从创建到使用的过程,包括字符串池的检查、字符串操作和不可变性原则。理解这个过程有助于更高效地使用 String 类。
Stirng的继承关系
在 Java 中,String
类最终继承自java.lang.Object
类,并且它实现了java.io.Serializable
、java.lang.Comparable<String>
和java.lang.CharSequence
接口。以下是用 Mermaid 语法展示的更详细的关系图:
说明如下:
Object
类:
- 所有 Java 对象的根类,
String
继承了Object
的一些通用方法,如toString()
、equals()
和hashCode()
等。
Serializable
接口:
- 标记接口,表示一个类的对象可以被序列化和反序列化。
String
类的对象可以被写入到输出流并从输入流中读取,从而实现序列化和反序列化操作。
Comparable<String>
接口:
- 定义了一个类型参数为
String
的泛型接口,用于定义对象之间的自然顺序。String
类实现了这个接口,意味着可以比较两个字符串的字典顺序。通过compareTo
方法可以比较两个字符串的大小关系。
CharSequence
接口:
- 表示一个字符序列。
String
类实现了这个接口,提供了一些方法来访问字符串中的字符,如length()
返回字符串的长度,charAt(int index)
返回指定索引处的字符,subSequence(int start, int end)
返回一个子序列。
缺点
由于String
的不可变性,在进行大量字符串操作时可能会创建很多中间对象,这可能会影响性能。为了避免这种情况,可以使用StringBuilder
或StringBuffer
类,它们是可变的字符串类,适用于频繁修改字符串的场景。
字符串的特性
字符串的连接
- 字符串连接:
String c = a + b
进行字符串连接操作。在 Java 中,使用+
运算符连接两个字符串时,实际上会创建一个新的String
对象。- 这个过程中,Java 会先创建一个
StringBuilder
(或StringBuffer
,在单线程环境下通常是StringBuilder
)对象,然后调用append
方法将a
和b
的内容添加到StringBuilder
中,最后调用toString
方法将StringBuilder
转换为String
对象,并将其赋值给c
。
String a = "abc";
String b = "MASU";
String c = a + b;
System.out.println(c); // 输出 "abcMASU"
注意事项
频繁进行字符串连接操作可能会在性能上产生一些开销,特别是在循环中进行大量的字符串连接时。因为每次连接都会创建新的 StringBuilder
和 String
对象。在这种情况下,可以考虑使用 StringBuilder
或 StringBuffer
显式地进行字符串连接操作,以提高性能。
StringBuilder builder = new StringBuilder();
builder.append("abc");
builder.append("MASU");
String c = builder.toString();
StringBuffer
基本介绍
StringBuffer
是 Java 中用于处理可变字符串的类。与String
类不同,String
对象是不可变的.StringBuffer
允许对字符串进行修改,例如添加、插入、删除字符等操作,且不会产生新的对象(除非重新赋值)。这在需要频繁修改字符串内容的场景中非常有用,能够避免创建大量中间字符串对象,从而提高性能。
StringBuffer 的继承结构图
- 常用方法
- 追加(append)方法
append
方法用于在StringBuffer
对象的末尾添加各种类型的数据,如字符、字符串、数字等。例如:
- 追加(append)方法
StringBuffer sb = new StringBuffer("Hello");sb.append(" World");System.out.println(sb.toString());//输出"Hello World"
- 它有多个重载版本,可以接受
char
、int
、long
、float
、double
、boolean
、char[]
、String
等多种类型的参数。 - 插入(insert)方法
- 用于在
StringBuffer
对象的指定位置插入各种类型的数据。例如:
- 用于在
StringBuffer sb = new StringBuffer("Hello");sb.insert(2, "inserted");System.out.println(sb.toString());//输出"Heinsertedllo"
-
它的第一个参数是插入的位置索引(从 0 开始),第二个参数是要插入的内容,同样有多个重载版本,可插入不同类型的数据。
-
删除(delete)方法
-
可以删除
StringBuffer
对象中指定位置的字符。例如:StringBuffer sb = new StringBuffer("Hello");sb.delete(1, 3);System.out.println(sb.toString());//输出"Hlo"
-
-
其参数
delete(start, end)
表示删除从start
(包含)到end
(不包含)位置的字符。 -
替换(replace)方法
- 用于替换
StringBuffer
对象中指定位置的字符。例如:
- 用于替换
StringBuffer sb = new StringBuffer("Hello");sb.replace(1, 3, "replaced");System.out.println(sb.toString());//输出"Hreplacedlo"
- 它的参数
replace(start, end, str)
表示将从start
(包含)到end
(不包含)位置的字符替换为str
。 - 反转(reverse)方法
- 可以将
StringBuffer
对象中的字符序列反转。例如:
- 可以将
StringBuffer sb = new StringBuffer("Hello");sb.reverse();System.out.println(sb.toString());//输出"olleH"
- 与 StringBuilder 的比较
StringBuilder
和StringBuffer
功能相似,都用于可变字符串的操作。主要区别在于StringBuffer
是线程安全的,其内部方法大多是synchronized
(同步)的,这使得它在多线程环境下能够正确运行,但性能上会有一定损耗。而StringBuilder
不是线程安全的,在单线程环境下性能更好,通常在不需要考虑线程安全的情况下,推荐使用StringBuilder
。
- 容量管理
StringBuffer
对象有一个容量(capacity)的概念,它表示StringBuffer
内部用于存储字符序列的缓冲区大小。当向StringBuffer
中添加字符,导致字符序列长度超过当前容量时,StringBuffer
会自动扩容。- 扩容的策略一般是:
新容量 = 旧容量 * 2 + 2
。例如,初始容量为 16,当字符序列长度超过 16 时,新容量可能会变为16*2 + 2=34
。可以通过capacity
方法查看当前容量,如System.out.println(sb.capacity());
。
StringBuffer常用方法
方法名 | 介绍 | 示例 |
---|---|---|
append(Object obj) | 将指定对象的字符串表示形式追加到当前StringBuffer 对象的末尾。可以接收多种数据类型,如String 、char 、int 、double 等 | StringBuffer sb = new StringBuffer("abc"); sb.append("def"); // sb的值变为"abcdef" |
insert(int offset, Object obj) | 在当前StringBuffer 对象的指定位置(offset )插入指定对象的字符串表示形式。offset 表示索引位置,从 0 开始计数 | StringBuffer sb = new StringBuffer("abc"); sb.insert(1, "x"); // sb的值变为"axbc" |
delete(int start, int end) | 删除当前StringBuffer 对象中从start (包括)到end (不包括)之间的字符 | StringBuffer sb = new StringBuffer("abcde"); sb.delete(1, 3); // sb的值变为"ade" |
replace(int start, int end, String str) | 将当前StringBuffer 对象中从start (包括)到end (不包括)之间的字符替换为指定的字符串str | StringBuffer sb = new StringBuffer("abcde"); sb.replace(1, 3, "xx"); // sb的值变为"axxde" |
reverse() | 反转当前StringBuffer 对象中的字符序列 | StringBuffer sb = new StringBuffer("abc"); sb.reverse(); // sb的值变为"cba" |
substring(int start) | 返回一个新的String ,它包含当前StringBuffer 对象从start 位置到末尾的字符序列 | StringBuffer sb = new StringBuffer("abcde"); String sub = sb.substring(2); // sub的值为"cde" |
substring(int start, int end) | 返回一个新的String ,它包含当前StringBuffer 对象从start (包括)到end (不包括)之间的字符序列 | StringBuffer sb = new StringBuffer("abcde"); String sub = sb.substring(1, 3); // sub的值为"bc" |
capacity() | 返回当前StringBuffer 对象的容量。容量是指用于存储字符序列的内部缓冲区大小,一般初始容量为 16,当内容超过容量时会自动扩容 | StringBuffer sb = new StringBuffer("abc"); System.out.println(sb.capacity()); // 可能输出16 |
length() | 返回当前StringBuffer 对象中字符序列的长度 | StringBuffer sb = new StringBuffer("abc"); System.out.println(sb.length()); // 输出3 |
setCharAt(int index, char ch) | 将当前StringBuffer 对象中指定索引(index )位置的字符设置为ch | StringBuffer sb = new StringBuffer("abc"); sb.setCharAt(1, 'x'); // sb的值变为"axc" |
StringBuilder
StringBuffer 的继承结构图
StringBuffer和StringBuilder的比较用表格
比较项目 | StringBuffer | StringBuilder |
---|---|---|
可变性 | 可变,允许通过多种方法(如 append、insert、delete 等)对字符串内容进行修改,修改操作在原对象上进行,不会产生新的对象(除非重新赋值) | 可变,提供与 StringBuffer 类似的修改方法,如 append、insert、delete 等,也是在原对象基础上进行修改 |
线程安全性 | 线程安全。其内部大部分方法都使用了synchronized 关键字修饰,这使得在多线程环境下,多个线程访问同一个 StringBuffer 对象时可以正确地同步,保证数据的一致性和正确性,但这也导致了一定的性能损耗 | 非线程安全。在单线程环境下,由于不需要进行同步操作,其性能比 StringBuffer 更好。在多线程环境下如果没有正确的外部同步机制,可能会导致数据不一致的问题 |
性能(单线程) | 由于同步机制的存在,在单线程频繁操作字符串的场景下,性能稍逊一筹 | 在单线程环境下,特别是频繁进行字符串操作(如大量的 append 操作)时,性能优于 StringBuffer,因为它不需要额外的同步开销 |
性能(多线程) | 可以安全地在多线程环境下使用,虽然同步机制会带来性能损失,但保证了数据的准确性 | 在多线程环境下,如果没有外部的同步措施,可能会出现数据错误,不过如果正确地进行外部同步(如使用锁),在性能优化较好的情况下可能会接近或优于 StringBuffer 的性能,但代码复杂度会增加 |
适用场景 | 适用于多线程环境下对字符串进行修改的场景,例如在多个线程可能同时访问和修改同一个字符串对象的服务器端程序、共享资源处理等情况 | 适用于单线程环境下对字符串进行高效操作的场景,如在一个简单的本地工具程序、临时字符串处理等情况下进行大量的字符串构建或修改操作 |
初始容量 | 可以通过构造函数指定初始容量,默认容量为 16。如果预估字符串长度变化较大,可以指定合适的初始容量以减少扩容操作 | 与 StringBuffer 类似,可以通过构造函数指定初始容量,默认容量为 16,也能在一定程度上通过合理设置初始容量优化性能 |
扩容策略 | 当内容长度超过容量时会自动扩容,一般扩容策略是新容量 = 旧容量 * 2 + 2 | 扩容策略与 StringBuffer 相同,当内容长度超过容量时会自动扩容,新容量 = 旧容量 * 2 + 2 |
相关文章:

Java基础-String Class(字符串类)
String Java String 类概览 String 类是 Java 中最常用的类之一,用于处理字符串。以下是 String 类的主要特性和操作: 特性/操作描述不可变性String 对象一旦创建就不能被修改创建方式使用双引号 “” 或 String 构造函数字符串池Java 维护字符串常量池…...

《Linux服务与安全管理》| 服务进程与网络配置
《Linux服务与安全管理》| 服务进程与网络配置 目录 《Linux服务与安全管理》| 服务进程与网络配置 (1) 写出查看NetworkManager服务状态的命令。 (2) 写出查看NetworkManager服务自启动状态的命令。 (3࿰…...

No.15 笔记 | CSRF 跨站请求伪造
目录 一、基础知识 (一)cookie 和 session、同源策略 (二)CSRF 原理 二、CSRF 类型 (一)GET 类型 (二)POST 类型 三、CSRF 实例讲解 (一)真实案例 &am…...
解决linux中pip速度过慢问题
在 Linux 系统下,如果你发现使用 pip 下载 Python 库时速度非常慢,可以考虑以下几种方法来加速下载: 使用 pip 的 -i 选项: 如果你只想临时使用其他镜像,可以在安装时加上 -i 选项: pip install package_n…...
FlinkSQL中 的 双流JOIN
在 Flink SQL 中,流与流的 JOIN 是一种复杂的操作,因为它涉及到实时数据的无界处理。理解 Flink SQL 流与流 JOIN 的底层原理和实现需要从多个角度来分析,包括 状态管理、事件时间处理、窗口机制 以及 内部数据流处理模型 等。下面将从这些角…...

Mysql(五) --- 数据库设计
文章目录 前言1.范式1.1.第一范式1.1.1 定义1.1.2.例子 1.2.第二范式1.2.1 定义1.2.2 例子1.2.3.不满足第二范式可能会出现的问题 1.3.第三范式1.3.1 定义2.3.2 示例 2. 设计过程3. 实体-关系图3.1 E-R图的基本组成3.2 关系的类型3.2.1 一对一关系(1:1)3.2.2 ⼀对多关系(1:N)3.…...

po框架的了解和应用
https://www.cnblogs.com/xiaolehong/p/18458470 笔记 任务:1、通过po框架输入测试报告 2、编写自动化测试框架 3、总结测试讲解稿 自动化测试框架概念: 自动化测试框架是一个集成体系,这个体系中包含测试功能的函数、测试数据源、测试对以及重要的模块。 作用:用于解决或…...

Linux云计算 |【第四阶段】RDBMS2-DAY5
主要内容: PXC概述、部署PXC(自动故障恢复测试)、存储引擎、读锁/写锁、表锁/行锁、常用的存储引擎介绍 一、PXC概述 PXC(Percona XtraDB Cluster,简称PXC集群),是基于Galera的MySQL高可用集群…...

从0开始深度学习(9)——softmax回归的逐步实现
文章使用Fashion-MNIST数据集,做一次分类识别任务 Fashion-MNIST中包含的10个类别,分别为: t-shirt(T恤)、trouser(裤子)、pullover(套衫)、dress(连衣裙&…...
Cannot inspect org.apache.hadoop.hive.serde2.io.HiveDecimalWritable 问题分析处理
报错; org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.UnsupportedOperationException: Cannot inspect org.apache.hadoop.hive.serde2.io.HiveDecimalWritable 该问题常见于parquet格式hive表查询时,一般原因为hive表对应数据文件元数据对应格式与…...

电子取证新视角:USB键盘流量提取密码方法研究与实现
0x01 引言 在当今数字化时代,USB设备的广泛使用使得信息安全和电子取证领域面临着新的挑战与机遇。特别是USB键盘,作为一种常见的输入设备,其流量中可能包含用户输入的敏感信息,如密码和其他私人数据。因此,研究USB键…...

Tongweb7049m4+THS6010-6012配置故障轉移+重試机制(by lqw)
使用场景 1.ths代理tongweb多套后端,假如有其中一套tongweb因为服务器重启或者宕机后没有及时启动,导致ths一直轮询在这个出故障的节点上。 2.即使在tongweb重启了,有的应用启动也需要一定的时间,这个时候只是启动了应用端口&…...

在线客服系统网站源码-网页聊天客服实现代码
源码简介 在线客服系统 – 网上客服系统,在线客服系统网站源码。 消息预知功能就是别人在聊天框打字你都能看到 1.新增客服坐席消息互动,客服之间可以互相接收消息,可以智能分配 2.新增消息预知功能,可提前预知访客已输入未发…...
JioNLP:一款实用的中文NLP预处理工具包
一、什么是 JioNLP? JioNLP是一个面向NLP开发者的工具包,提供了常见的中文文本预处理、解析等功能,使用简单、高效准确、无需配置,可极大加快NLP项目的开发进度。 主要特点包括: 代码开源,使用MIT协议功能丰富,涵盖多个NLP预处理需求使用简单,无需复杂配置即可调用准确高效…...

GR-ConvNet论文 学习笔记
GR-ConvNet 文章目录 GR-ConvNet前言一、引言二、相关研究三、问题阐述四、方法A.推理模块B.控制模块C.模型结构D.训练方法E.损失函数 五、评估A.数据集B.抓取评判标准 六、实验A.设置B.家庭测试物体C.对抗性测试物体D.混合物体 七、结果A.康奈尔数据集B.Jacquard数据集C.抓取新…...
windows环境批量删除指定目录下的全部指定文件
写在开头: 1. 涉及文件删除,先在小范围内测试(更改D:\扫描文件路径) 2. 命令会递归该目录下的所有文件 命令: forfiles /p D:\ /s /m _maven.repositories /c "cmd /c del path"解释: /p D:\ …...

水深探测仪的作用和使用方法
在水域救援的行动里,救援人员时刻面临着复杂多变、充满未知的水域状况。当接到救援任务奔赴现场,那片需要涉足的水域就像一个神秘莫测的异世界,挑战着所有人的认知与勇气。 水深探测仪作为一种专用于测量水域深度的设备,通过声波和…...

Leetcode 搜索插入位置
这段代码的核心思想是 二分查找,用于在一个已经排序的数组中查找目标值的位置。如果目标值存在于数组中,返回它的索引;如果目标值不存在,返回它按顺序应该插入的位置。 算法思想步骤: 定义左右边界: 我们使…...
jsp怎么实现点赞功能
在JSP中实现点赞功能通常涉及前端页面的设计、后端逻辑处理以及数据存储。为了实现点赞功能,你可以使用以下步骤: 前端(JSP页面)设计 前端部分包括显示点赞按钮,并通过Ajax发送点赞请求,以避免页面刷新。 …...
取消microsoft edge作为默认浏览器 ,修改方法,默认修改不了的原因
将Microsoft Edge或其它浏览器设置为默认浏览器,可以尝试以下方法来解决此问题: 一, 通过浏览器设置修改:打开Microsoft Edge浏览器,单击右上角的“更多”按钮,然后选择“设置”。在设置页面左侧找到“默认…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...

DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...