Java字符串

目录

一、String类

1. 概述

2. 创建方式

(1)直接赋值

(2)使用new关键字

3. 性能优化

4. 常用方法

(1)==

(2)equals()

(3)concat()

二、StringBuilder类

1. 概述

2. 核心特性

3. 常用方法

(1)append

(2)insert

(3)delete

(4)reverse

(5)toString

4. 性能优化技巧

(1)预设容量(Pre-sizing)

(2)链式调用优化(Method Chaining)

(3)避免循环内重复创建

(4)批量操作替代单个操作

三、StringBuffer类

1. 概述

2. 核心特性

3. 适用场景

四、StringJoiner类

1. 概述

2. 核心特性

3. 基本构造方式

4. 常用方法

(1)add

(2)merge

(3)toString

五、字符串拼接的底层原理

1. 使用+操作符拼接

(1)没有变量(纯字面量拼接)

(2)有变量(涉及变量拼接)

2. 使用String.concat()方法

3. 使用StringBuilder或StringBuffer


Java中的字符串处理类包括StringStringBuilderStringBufferStringJoiner等,它们各自有不同的特性和底层实现原理。

一、String

1. 概述

String类位于java.lang包中,是Java中最基础的字符串类,其底层是一个被final修饰的字符数组char[] value( JDK9及之后,为了节省内存空间,改为使用byte[]数组存储字符 ),这意味着一旦创建,其内容不可更改。这种不可变性使得String在多线程环境下是安全的,但同时也带来了性能开销,因为每次修改都需要创建新的对象。

2. 创建方式

(1)直接赋值

比如 String s = "abc"; 。当使用双引号直接赋值时,系统会检查该字符串在串池中是否存在,如果不存在就创建新的字符串,如果存在就复用。

(2)使用new关键字

比如 String s = new String("abc"); 。这种方式会创建新的字符串对象,每new一次就会在堆内存里开辟一块新的空间并创建新的对象,占用额外的内存。

常用构造方法

  • String():创建一个空字符串。

  • String(String original):根据传入的字符串创建一个新的字符串对象。

  • String(char[] value):根据字符数组创建一个新的字符串对象。

 public static void main(String[] args) {
     char[] chars = {'a', 'b', 'c', 'd'};
     String s = new String(chars);
     System.out.println(s);  // abcd
 }
  • String(byte[] bytes, Charset charset):根据字节数组和指定的字符集创建一个新的字符串对象。

 public static void main(String[] args) {
     byte[] bytes = {97, 98, 99, 100};
     String s = new String(bytes);
     System.out.println(s);  // abcd
 }

3. 性能优化

  • 使用字符串常量池避免重复创建相同字符串。

  • 避免频繁修改字符串,因为每次修改都会导致新对象的创建。

4. 常用方法

(1)==

如果是基本数据类型, == 比较的是数据值;如果是引用数据类型, == 比较的是地址值。字符串是引用数据类型,所以比较的是地址值。

 public static void main(String[] args) {
     String s1 = new String("abc");  // s1记录的是堆里面的地址值
     String s2 = "abc";  // s2记录的是串池中的地址值
     System.out.println(s1 == s2);  // false
 }
(2)equals()

equals() 比较的是字符串内容。如果要忽略大小写的比较,可以使用 equalsIgnoreCase()

 public static void main(String[] args) {
     String s1 = new String("abc");
     String s2 = "abc";
     System.out.println(s1.equals(s2));  // true
 }
(3)concat()

concat() 方法会创建一个新的字符串对象,效率较低。

二、StringBuilder

1. 概述

StringBuilder是可变字符串类(可以看作一个容器),其底层同样是一个字符数组(char[] value),但与String不同的是,它允许动态修改内容,因此比String更高效。

2. 核心特性

  1. 可变性(Mutable) :内容可被修改而不产生新对象。

  2. 非线程安全(Not Thread-Safe) :比线程安全的StringBuffer性能更高。

  3. 动态扩容(Dynamic Expansion) :自动增加内部缓冲区容量。

  4. 高效操作(Efficient Operations) :避免频繁内存分配。

3. 常用方法

(1)append
 StringBuilder sb = new StringBuilder("abc");
 ​
 // 基本类型追加(自动转换为字符串)
 sb.append(def)
 sb.append(123)
 sb.append(2.5)
 sb.append(true)
 ​
 // 对象追加(调用toString())
 sb.append(Object obj)
 ​
 // 子串追加(支持偏移量)
 sb.append(char[] str, int offset, int len)
 sb.append(CharSequence s, int start, int end)
(2)insert
 sb.insert(int offset, boolean b)
 sb.insert(int offset, char c)
 sb.insert(int offset, int i)
 sb.insert(int offset, Object obj)
(3)delete
 sb.delete(int start, int end)  // 删除[start,end)区间内容  
 sb.deleteCharAt(int index)  // 删除指定位置字符  
(4)reverse
 sb.reverse()  // 原地反转字符序列  
(5)toString
 String str = sb.toString();  // 转换为不可变字符串

4. 性能优化技巧

(1)预设容量(Pre-sizing)
 // 预估最终长度设置初始容量  
 StringBuilder sb=new StringBuilder(1024); 
(2)链式调用优化(Method Chaining)
 sb.append("a").append("b").append("c").reverse().toString();
(3)避免循环内重复创建
 // 错误示范(每次循环都新建)
 for(...){ sb=new StringBuilder(); }
 ​
 // 正确做法(复用同一个)
 StringBuilder sb=new StringBuilder();
 for(...){ sb.setLength(0); }
(4)批量操作替代单个操作
 // 低效方式  
 for(char c:chars){ sb.append(c); }
 ​
 // 高效方式  
 sb.append(chars);

三、StringBuffer

1. 概述

StringBufferStringBuilder 非常相似,但是其特点是线程安全。因为其方法被 synchronized 修饰,这使得它适用于多线程环境,但因此带来了性能开销。

2. 核心特性

  • 线程安全(Thread-Safe) :所有公开方法都使用 synchronized

  • 可变性(Mutable) :内容可被修改而不产生新对象。

  • 动态扩容(Dynamic Expansion) :自动增加内部缓冲区容量。

  • 兼容性(Compatibility) :从Java1.0开始就存在。

3. 适用场景

适用于多线程环境下需要修改字符串的场景。在多线程环境下使用时,可以避免锁竞争问题,但在单线程环境下不如StringBuilder高效。

四、StringJoiner

1. 概述

StringJoiner 是Java8引入的一个专门用于构造由分隔符分隔的字符序列的工具类,它简化了集合元素连接、CSV格式生成等常见场景下的字符串拼接操作。

2. 核心特性

  • 分隔符控制(Delimiter) :可指定固定分隔符连接元素。

  • 前后缀支持(Prefix/Suffix) :可为结果添加统一的前后缀。

  • 空值处理(Null Handling) :提供灵活的空元素处理策略。

  • 链式调用(Fluent API) :支持方法链式调用风格。

3. 基本构造方式

 // 仅指定分隔符(无前后缀)
 new StringJoiner(",")
 ​
 // 完整构造(带前后缀)
 new StringJoiner(",", "[", "]")

4. 常用方法

(1)add
 StringJoiner sj = new StringJoiner(",");
 ​
 // 添加单个元素(支持任意CharSequence)
 sj.add("A").add("B").add("C");
 ​
 // 添加多个元素的快捷方式(Java8+)
 List<String> list = Arrays.asList("X","Y","Z");
 list.forEach(joiner::add);
(2)merge
 // 合并另一个StringJoiner的内容(忽略其前后缀)
 StringJoiner sj1 = new StringJoiner(",", "[", "]");
 StringJoiner sj2 = new StringJoiner(",", "[", "]");
 sj1.add("A").add("B");
 sj2.add("X").add("Y");
 sj1.merge(sj2);
 System.out.println(sj1);  // 输出:[A,B,X,Y]
(3)toString
 String str = sj1.toString();
 System.out.println(str);  // 输出:[A,B,X,Y]

五、字符串拼接的底层原理

1. 使用+操作符拼接

(1)没有变量(纯字面量拼接)

当拼接的内容全部是字符串字面量时,Java编译器会在编译阶段直接将其优化为一个常量字符串,优化后的字符串会被存储在字符串常量池中,避免运行时创建额外的对象。

 String result = "Hello" + "World";
 // 上述代码会被编译器优化为:
 String result = "HelloWorld";

性能特点

  • 高效:由于编译期优化,运行时无需创建StringBuilder对象,性能最佳。

  • 内存节省:字符串直接存储在常量池中,减少内存开销。

(2)有变量(涉及变量拼接)

当拼接的内容包括变量时:JDK8以前,系统底层会创建一个StringBuilder对象,依次调用append()方法将每个字符串片段添加到StringBuilder对象中,然后调用toString()方法将StringBuilder对象转换为String对象,而toString()方法的底层是直接new了一个字符串对象。JDK8及以后,系统会预估字符串拼接之后的总大小,把要拼接的内容都放在数组里,本质上也是产生了一个新的字符串。

 String str1 = "Hello";
 String str2 = "World";
 String result = str1 + str2;
 // 上述代码会被编译器转换为:
 String str1 = "Hello";
 String str2 = "World";
 String result = new StringBuilder().append(str1).append(str2).toString();

性能特点

  • 运行时开销:每次拼接都会创建StringBuilder对象,增加运行时开销。

  • 内存开销:生成的字符串存储在堆内存中,而不是常量池中。

2. 使用String.concat()方法

String.concat()方法用于将指定字符串连接到此字符串的末尾。它实际上是通过创建一个新的字符数组,将两个字符串的内容复制到新数组中,然后构造一个新的String对象。

性能特点

  • concat()方法每次调用都会创建一个新的String对象,因此在频繁拼接字符串时性能较差,适用于少量字符串的拼接。

3. 使用StringBuilder或StringBuffer

StringBuilder和StringBuffer都提供了可变的字符序列,允许对字符串内容进行修改而不需要创建新的对象。执行流程:创建一个StringBuilder或StringBuffer对象,调用append()方法将每个字符串片段添加到对象中,调用toString()方法将对象转换为String对象。

性能特点

  • StringBuilder是非线程安全的,但性能较高。StringBuffer是线程安全的,但性能稍低(因为添加了同步机制)。

  • 在需要频繁拼接字符串的场景中,使用StringBuilder或StringBuffer可以显著提高性能。

  • StringBuilder适用于单线程环境,而StringBuffer适用于多线程环境。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值