Java字符串详解
String:
String
是不可变的。一旦创建了字符串对象,其内容不能被修改。每次对字符串进行修改(如连接、替换等)都会创建一个新的字符串对象。
1. 字符串的创建(构造方法)
public class StringDemo01 {public static void main(String[] args) {String s1 = new String();System.out.println("s1:" + s1);char[] chs = {'a', 'b', 'c'};String s2 = new String(chs);System.out.println("s2:" + s2);byte[] bys = {97, 98, 99};String s3 = new String(bys);System.out.println("s3:" + s3);//直接赋值String s4 = "abc";System.out.println("s4:" + s4);}
}
2. 常用方法示例
package JavaProjets; public class Main { public static void main(String[] args) { String a="WaRren"; int length = a.length();//获取字符串长度 char c = a.charAt(0);//获取指定位置的字符 String str1 = "Hello";String str2 = " World";String result = str1.concat(str2); // "Hello World",字符串的拼接 System.out.println(a.substring(0, 2));//截取字符串 System.out.println(a.replace("W", "H"));//替换 a.toLowerCase();//转为小写 a.toUpperCase();//转为大写 String s="Wa"; String x="Wb";System.out.println(s.compareTo(x));//比较字符串的大小,返回一个整数,这里是-1String s = String.valueOf(123);//将其他数据类型转换为字符串。boolean b = s instanceof String; System.out.println(b);String k =" hell o "; System.out.println(k.trim());//去掉字符串两端的空格.}
}
字符串的比较
- 使用
==
号比较基本数据类型时,比较的是内容(数据值), - 使用
==
号比较引用数据类型,如字符串时,比较的是两个对象的引用(地址)是否相同,而不是内容.
1. 引用(地址)比较
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1 == str2); // 输出 false,因为 str1 和 str2 指向的是不同的对象String str3 = "hello";
String str4 = "hello";
System.out.println(str3 == str4); // 输出 true,因为 str3 和 str4 指向的是相同的常量池中的对象
-
new String("hello")
每次都会在堆上创建一个新的String
对象,因此str1
和str2
的引用地址不同。 -
"hello"
是字符串常量,它在字符串池中只有一份,因此str3
和str4
指向的是同一个对象。 -
在 Java 中,为了提高效率和节省内存,当直接使用字符串字面量(如 “hello”)创建字符串对象时,如果字符串常量池中已经存在相同的字符串,就会让新创建的引用指向常量池中的已有对象,而不是在堆内存中创建新的对象。
2. 内容比较
equals
用于比较两个字符串内容是否相同、区分大小写.
String str1 = new String("hello");String str2 = new String("hello");System.out.println(str1.equals(str2)); // 输出: true
equalsIgnoreCase()
用于比较两个字符串的内容是否相等,忽略大小写。
public class Main {public static void main(String[] args) {String str1 = "Hello";String str2 = "hello";String str3 = "World";boolean result1 = str1.equalsIgnoreCase(str2); // 返回 trueboolean result2 = str1.equalsIgnoreCase(str3); // 返回 falseSystem.out.println("str1 equals str2 (ignore case): " + result1); //trueSystem.out.println("str1 equals str3 (ignore case): " + result2); //false}
}
StringBuilder:
- 一个容器,创建后里面的内容可变.
- 在频繁拼接和反转字符串时会用到.
public class Main {public static void main(String[] args) {StringBuilder sb = new StringBuilder();// 添加字符串sb.append("Hello");sb.append(", ");sb.append("World!");System.out.println(sb.toString()); // 输出: Hello, World!// 插入字符串sb.insert(5, " Java");System.out.println(sb.toString()); // 输出: Hello Java, World!// 删除字符串sb.delete(5, 10);System.out.println(sb.toString()); // 输出: Hello, World!// 反转字符串sb.reverse();System.out.println(sb.toString()); // 输出: !dlroW ,olleH//替换字符串sb.replace(6, 11, "Java"); // 替换索引 6 到 11 之间的字符为 "Java"System.out.println(sb.toString()); }
}
为什么频繁拼接字符串建议使用StringBuilder而不是+?
-
字符串通过
+
拼接的方式, 实际上是通过StringBuilder
调用append()
方法实现的,拼接完成之后调用toString()
得到一个String
对象; -
不过,在循环内使用
+
进行字符串的拼接的话,存在比较明显的缺陷:编译器不会创建单个StringBuilder
以复用,会创建过多的StringBuilder
对象。 -
所以建议直接使用
StringBuilder
是否为对称字符串
package Works; public class Main { public static void main(String[] args) { // 使用条件表达式输出结果 System.out.println(isPalindrome("waaw") ? "true" : "false"); } public static boolean isPalindrome(String string){ StringBuilder sb = new StringBuilder(); // 检查字符串是否是回文 return sb.append(string).reverse().toString().equals(string); }
}
转化为字符串:
public class StringBuilderDemo7 {public static void main(String[] args) {int[] arr = {1,2,3};//调用方法把数组变成字符串String str = arrToString(arr);System.out.println(str);}public static String arrToString(int[] arr){StringBuilder sb = new StringBuilder();sb.append("[");for (int i = 0; i < arr.length; i++) {if(i == arr.length - 1){sb.append(arr[i]);}else{sb.append(arr[i]).append(", ");}}sb.append("]");return sb.toString();}
}
链式编程
- 简化代码
package JavaProjets; public class Main { public static void main(String[] args) { String result = new StringBuilder() .append("Hello") .append(" ") .append("World") .toString(); System.out.println(result); }
}
StringBuffer
StringBuffer的方法和StringBuilder类似,不同点如下:
- StringBuffer是线程安全的,StringBuilder不是
- StringBuffer性能比StringBuilder差一些
选择:
-
在多线程环境下,且对线程安全有要求时,使用
StringBuffer
会更合适。 -
在单线程环境下,尤其是性能要求较高的场景下,推荐使用
StringBuilder
,因为它没有线程安全的同步开销。
StringJoiner
StringJoiner
: Java 8 后出现,用于拼接多个字符串,适合需要使用分隔符、前缀和后缀的场景。
示例
import java.util.StringJoiner;public class StringJoinerExample {public static void main(String[] args) {StringJoiner joiner = new StringJoiner(", ", "[", "]");joiner.add("Apple");joiner.add("Banana");joiner.add("Cherry");String result = joiner.toString();//转化拼接后的对象为字符串System.out.println(result); // 输出: [Apple, Banana, Cherry]}
}
- 频繁拼接字符串时,推荐使用
StringBuilder
或StringBuffer
来提高性能。
对比
String
不可变,线程安全;StringBuffer
对方法加了同步锁或者对调用的方法加了同步锁,线程安全;StringBuilder
并没有对方法进行加同步锁,非线程安全。
对于三者使用的总结:
- 操作少量的数据: 适用
String
- 单线程操作字符串缓冲区下操作大量数据: 适用
StringBuilder
- 多线程操作字符串缓冲区下操作大量数据: 适用
StringBuffer