目录
一.String类
1.字符串的构造
2.字符串的特点(重点)
3.String对象的比较
4.字符串查找
5.转换
6.字符串拆分
7.字符串截取
8.其他操作方法
二. StringBuilder和StringBuffer
1.特点
2.StringBuilder 和 StringBuffer的区别
一.String类
1.字符串的构造
字符串的构造方式有很多种,但是我这里就举例三种常用的方式:
//直接使用字符串构造
String s="abc";
System.out.println(s);//new一个String类对象
String s1=new String("abc");
System.out.println(s1);//利用char数组来new一个String对象
char[] ch={'a','b','c'};
String s2=new String(ch);
System.out.println(s2);
当然如果想要了解更多,可以访问这个网站查阅:Java Platform SE 8
2.字符串的特点(重点)
2.1不可变性
在 Java 中,
String
类被设计为不可变的,即字符串对象一旦创建,其内容就无法修改。任何试图修改字符串的操作(如拼接、替换等)实际上会创建一个新的字符串对象,而不会更改原来的对象。
比如:
String str1 = "Hello";
String str2 = str1.concat(" World");
// str1仍然是 "Hello",str2是 "Hello World"
解释:调用
concat
方法并没有修改str1
,而是生成了一个新的字符串str2
。
优点:
1.尽管每次修改都会创建新的字符串对象,看似增加了内存开销和处理时间,但 JVM 的优化和垃圾回收机制能够有效管理这些开销。
2.不可变性防止了字符串被不小心或恶意修改。
3.由于字符串是不可变的,可以安全地在多线程环境中共享而不需要同步。
2.2字符串池
字符串池是 JVM 内存中的一个特殊区域,用于存储字符串字面量。在创建字符串时,如果字符串的值已经存在于池中,JVM 会返回池中已有的字符串对象,而不是创建一个新的。这种机制避免了重复的字符串对象,从而节省内存。
比如:
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2); // 输出 true
解释:
str1
和str2
都指向同一个字符串池中的对象,因此==
比较返回true
。
字符串池的使用:
String str1 = new String("Hello");
String str2 = str1.intern();
String str3 = "Hello";
System.out.println(str2 == str3); // 输出 true
解释:
字面量创建:使用双引号创建的字符串会被自动放入字符串池中。例如,
String str = "Hello";
会将"Hello"
放入池中。显式创建:通过
new
关键字创建的字符串不会自动加入字符串池。例如,String str = new String("Hello");
会创建一个新的字符串对象,而不是从池中获取。
intern
方法:String
类的intern
方法可以将字符串显式加入字符串池。如果池中已经存在相同值的字符串,则返回池中的引用;否则,将该字符串加入池中,并返回它的引用。
注意事项:
String是引用类型,内部并不存储字符串本身,我们可以查看String类的实现源码:
这样的话不仅提高了内存效率还节省了内存消耗。
与此同时,我们可以看到该数组被final修饰,final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内 容是可以修改的。所有对字符串的操作方法(如
substring
、concat
)都返回新的字符串对象,而不是修改原来的字符串。
public static void main(String[] args) {// s1和s2引用的是不同对象 s1和s3引用的是同一对象String s1 = new String("hello");String s2 = new String("world");String s3 = s1;System.out.println(s1.length()); // 获取字符串长度---输出5System.out.println(s1.isEmpty()); // 如果字符串长度为0,返回true,否则返回false
}
// 打印"hello"字符串(String对象)的长度
System.out.println("hello".length());
3.String对象的比较
3.1使用 ==
运算符
对于基本类型变量,==比较两个变量中存储的值是否相同。
对于引用类型变量,==比较两个引用变量引用的是否为同一个对象。注意:String是引用类型
//基本类型
int a = 10;
int b = 20;
int c = 30;
System.out.println(a == b); // false
System.out.println(a == c); // true//String引用类型
String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");
System.out.println(str1 == str2); // 输出 true
System.out.println(str1 == str3); // 输出 false
3.2使用 equals()
方法
String类重写了父类Object中equals方法,Object中equals默认按照==比较。
equals()
方法比较的是两个字符串对象的内容是否相同。
String str1 = "Hello";
String str2 = new String("Hello");System.out.println(str1.equals(str2)); // 输出 true//equals() 方法比较的是 str1 和 str2 的字符序列,它们的内容相同,所以返回 true。
3.3区分大小写的比较
equals()
方法默认是区分大小写的。如果需要忽略大小写进行比较,可以使用equalsIgnoreCase()
方法。
String str1 = "Hello";
String str2 = "hello";System.out.println(str1.equals(str2)); // 输出 false
System.out.println(str1.equalsIgnoreCase(str2)); // 输出 true
3.4按照字典顺序比较(compareTo(String s)方法)
compareTo()
方法:用于按照字典顺序比较两个字符串。与equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型,比较方式:
1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值。
2. 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值。
public static void main(String[] args) {String s1 = new String("abc");String s2 = new String("ac");String s3 = new String("abc");String s4 = new String("abcdef");System.out.println(s1.compareTo(s2)); // 不同输出字符差值-1System.out.println(s1.compareTo(s3)); // 相同输出 0System.out.println(s1.compareTo(s4)); // 前k个字符完全相同,输出长度差值 -3
}
3.5compareToIgnoreCase(String str) 方法忽略大小比较
compareToIgnoreCase(String str)
方法和compareTo()
方法差不多,只不过是忽略了大小的比较。
public class CompareToIgnoreCaseExample {public static void main(String[] args) {String str1 = "hello";String str2 = "HELLO";String str3 = "world";// 比较 str1 和 str2int result1 = str1.compareToIgnoreCase(str2);System.out.println(result1); // 输出 0// 比较 str1 和 str3int result2 = str1.compareToIgnoreCase(str3);System.out.println(result2); // 输出负数}
}
//str1.compareToIgnoreCase(str2):由于 str1 和 str2 内容相同,但大小写不同,方法忽略了大小写差异,因此返回 0,表示它们相等。
//str1.compareToIgnoreCase(str3):str1 和 str3 内容不同,按照字典顺序比较,"hello" 小于 "world",所以返回负数。
4.字符串查找
方法 | 功能 |
char charAt(int index) | 返回index位置上字符,如果index为负数或者越界,抛出 IndexOutOfBoundsException异常 |
int indexOf(int ch) | 返回ch第一次出现的位置,没有返回-1 |
int indexOf(int ch, int fromIndex) | 从fromIndex位置开始找ch第一次出现的位置,没有返回-1 |
int indexOf(String str) | 返回str第一次出现的位置,没有返回-1 |
int indexOf(String str, int fromIndex) | 从fromIndex位置开始找str第一次出现的位置,没有返回-1 |
int lastIndexOf(int ch) | 从后往前找,返回ch第一次出现的位置,没有返回-1 |
int lastIndexOf(int ch, int fromIndex) | 从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返 回-1 |
int lastIndexOf(String str) | 从后往前找,返回str第一次出现的位置,没有返回-1 |
int lastIndexOf(String str, int fromIndex) | 从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返 回-1 |
public class StringMethodsExample {public static void main(String[] args) {String str = "Hello, world!";// 使用 charAt() 方法try {char charAtIndex = str.charAt(4); // 获取索引4的字符System.out.println("charAt(4): " + charAtIndex); // 输出: o} catch (StringIndexOutOfBoundsException e) {System.out.println("Index out of bounds in charAt()");}// 使用 indexOf() 方法int firstIndexOfH = str.indexOf('H'); // 查找字符'H'首次出现的位置System.out.println("indexOf('H'): " + firstIndexOfH); // 输出: 0// 使用 indexOf() 方法并指定起始位置int indexOfOFrom5 = str.indexOf('o', 5); // 从索引5开始查找字符'o'System.out.println("indexOf('o', 5): " + indexOfOFrom5); // 输出: 8// 使用 indexOf() 查找子字符串int indexOfWorld = str.indexOf("world"); // 查找子字符串"world"System.out.println("indexOf('world'): " + indexOfWorld); // 输出: 7// 使用 indexOf() 查找子字符串并指定起始位置int indexOfWorldFrom5 = str.indexOf("world", 5); // 从索引5开始查找子字符串"world"System.out.println("indexOf('world', 5): " + indexOfWorldFrom5); // 输出: 7// 使用 lastIndexOf() 方法int lastIndexOfO = str.lastIndexOf('o'); // 从末尾开始查找字符'o'最后一次出现的位置System.out.println("lastIndexOf('o'): " + lastIndexOfO); // 输出: 8// 使用 lastIndexOf() 方法并指定起始位置int lastIndexOfOFrom5 = str.lastIndexOf('o', 5); // 从索引5向前查找字符'o'System.out.println("lastIndexOf('o', 5): " + lastIndexOfOFrom5); // 输出: 4// 使用 lastIndexOf() 查找子字符串int lastIndexOfWorld = str.lastIndexOf("world"); // 从末尾开始查找子字符串"world"System.out.println("lastIndexOf('world'): " + lastIndexOfWorld); // 输出: 7// 使用 lastIndexOf() 查找子字符串并指定起始位置int lastIndexOfWorldFrom5 = str.lastIndexOf("world", 5); // 从索引5向前查找子字符串"world"System.out.println("lastIndexOf('world', 5): " + lastIndexOfWorldFrom5); // 输出: 7}
}
5.转换
5.1 字符串与字符数组的转换
public static void main(String[] args) {String str = "Hello";// 将字符串转换为字符数组char[] charArray = str.toCharArray();System.out.println("charArray: " + java.util.Arrays.toString(charArray)); // 输出: [H, e, l, l, o]// 将字符数组转换为字符串String newStr = new String(charArray);System.out.println("newStr: " + newStr); // 输出: Hello}
toCharArray()
:将字符串转换为字符数组。String(char[] value)
:将字符数组转换为字符串。
5.2 字符串与整数的转换
public static void main(String[] args) {String str = "123";// 将字符串转换为整数int num = Integer.parseInt(str);System.out.println("num: " + num); // 输出: 123// 将整数转换为字符串String newStr = String.valueOf(num);System.out.println("newStr: " + newStr); // 输出: 123}
Integer.parseInt(String s)
:将字符串转换为整数。String.valueOf(int i)
:将整数转换为字符串。
5.3 字符串与浮点数的转换
public static void main(String[] args) {String str = "123.45";// 将字符串转换为浮点数double num = Double.parseDouble(str);System.out.println("num: " + num); // 输出: 123.45// 将浮点数转换为字符串String newStr = String.valueOf(num);System.out.println("newStr: " + newStr); // 输出: 123.45}
Double.parseDouble(String s)
:将字符串转换为浮点数。String.valueOf(double d)
:将浮点数转换为字符串。
5.4 字符串与布尔值的转换
public static void main(String[] args) {String str = "true";// 将字符串转换为布尔值boolean bool = Boolean.parseBoolean(str);System.out.println("bool: " + bool); // 输出: true// 将布尔值转换为字符串String newStr = String.valueOf(bool);System.out.println("newStr: " + newStr); // 输出: true}
Boolean.parseBoolean(String s)
:将字符串转换为布尔值。String.valueOf(boolean b)
:将布尔值转换为字符串。
5.5 字符串与其他类型的转换(如日期等)
import java.text.SimpleDateFormat;
import java.util.Date;public class StringConversion {public static void main(String[] args) throws Exception {// 创建一个字符串,表示日期String dateStr = "2025-01-12";// 创建一个SimpleDateFormat对象,用于定义日期格式// "yyyy-MM-dd" 表示日期的格式是 "年-月-日",例如 2025-01-12SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");// 使用 parse() 方法将字符串转换为 Date 对象// parse() 方法会根据 SimpleDateFormat 中定义的格式来解析字符串Date date = sdf.parse(dateStr);// 输出转换后的 Date 对象,输出格式会根据默认的日期格式进行显示// 输出:Sat Jan 12 00:00:00 CST 2025System.out.println("Date: " + date); // 使用 format() 方法将 Date 对象转换回字符串// format() 方法会根据 SimpleDateFormat 中定义的格式,将 Date 转换为符合该格式的字符串String formattedDate = sdf.format(date);// 输出转换回的字符串,输出结果将符合 "yyyy-MM-dd" 格式// 输出:2025-01-12System.out.println("Formatted Date: " + formattedDate); }
}
5.6. 基本类型与字符串的转换
public static void main(String[] args) {int num = 456;// 基本类型转换为字符串String str = String.valueOf(num);System.out.println("str: " + str); // 输出: 456// 字符串转换为基本类型int numFromStr = Integer.parseInt(str);System.out.println("numFromStr: " + numFromStr); // 输出: 456}
6.字符串拆分
6.1基本用法
split(String regex)
:根据正则表达式将字符串分割成数组。
public static void main(String[] args) {// 定义一个包含逗号分隔符的字符串String str = "apple,banana,orange,grape";// 使用 split() 方法将字符串拆分为数组String[] fruits = str.split(",");// 输出拆分后的结果for (String fruit : fruits) {System.out.println(fruit); }}
输出:
6.2限制分割次数
split(String regex, int limit)
:可以指定拆分的次数(limit
参数)。如果指定了限制,那么返回的数组将最多包含limit
个元素,剩余的部分将合并到最后一个元素中。
public static void main(String[] args) {// 定义一个包含多个逗号分隔符的字符串String str = "apple,banana,orange,grape";// 使用 split() 方法将字符串拆分为最多两个部分String[] fruits = str.split(",", 2);// 输出拆分后的结果for (String fruit : fruits) {System.out.println(fruit);}}
输出:
6.3 使用正则表达式进行拆分
public static void main(String[] args) {// 定义包含多个空格和逗号的字符串String str = "apple, banana orange,grape";// 使用改进后的正则表达式进行拆分String[] fruits = str.split(",\\s*|\\s+");// 输出拆分后的结果for (String fruit : fruits) {System.out.println(fruit);}}
输出:
解释:
1.
,\\s*
,
:这是一个字面量字符,表示逗号,
。它将匹配逗号本身。
\\s*
:匹配零个或多个空白字符。
\\s
匹配任何空白字符,如空格、制表符、换行符等。
*
是量词,表示“匹配零次或多次”。2.
\\s+
\\s
:匹配任何空白字符,包括空格、制表符、换行符等。
+
:量词,表示“匹配一次或多次”,即匹配一个或多个空白字符。
6.4 空字符串的拆分
当字符串中存在连续的分隔符时,
split()
方法将返回包含空字符串的数组元素。
public static void main(String[] args) {// 定义一个包含连续逗号的字符串String str = "apple,,banana,,orange";// 使用 split() 方法拆分字符串String[] fruits = str.split(",");// 输出拆分后的结果for (String fruit : fruits) {System.out.println("[" + fruit + "]");}}
输出:
注意:在连续的分隔符
,,
之间会返回空字符串""
。
7.字符串截取
substring()
方法有两种常见的重载形式:
substring(int beginIndex)
:
- 返回一个从指定位置(
beginIndex
)到字符串结尾的子字符串。beginIndex
是起始位置,索引从0
开始。substring(int beginIndex, int endIndex)
:
- 返回一个从
beginIndex
到endIndex
(不包括endIndex
)的子字符串。beginIndex
是起始位置,endIndex
是结束位置,但不包括endIndex
处的字符。
示例
1. 从指定位置截取到字符串末尾
public static void main(String[] args) {String str = "Hello, World!";// 从索引 7 开始截取String substr = str.substring(7);System.out.println(substr); // 输出: World!}
2. 截取指定范围的子字符串
public static void main(String[] args) {String str = "Hello, World!";// 截取从索引 0 到 5(不包括索引 5)的子字符串String substr = str.substring(0, 5);System.out.println(substr); // 输出: Hello}
8.其他操作方法
方法 | 功能 |
String trim() | 去掉字符串中的左右空格,保留中间空格 |
String toUpperCase() | 字符串转大写 |
String toLowerCase() | 字符串转小写 |
public static void main(String[] args) {String str = " HeLLo, WoRLD! ";// 使用 trim() 去除两端的空白字符String trimmedStr = str.trim();System.out.println("Trimmed: '" + trimmedStr + "'"); // 输出: 'HeLLo, WoRLD!'// 使用 toUpperCase() 将所有字符转换为大写String upperCaseStr = trimmedStr.toUpperCase();System.out.println("Uppercase: '" + upperCaseStr + "'"); // 输出: 'HELLO, WORLD!'// 使用 toLowerCase() 将所有字符转换为小写String lowerCaseStr = trimmedStr.toLowerCase();System.out.println("Lowercase: '" + lowerCaseStr + "'"); // 输出: 'hello, world!'}
输出结果:
二. StringBuilder和StringBuffer
StringBuilder
和StringBuffer
是 Java 中用于操作字符串的两个类,它们的主要功能是提供一个可变的字符序列,与String
不同,String
是不可变的。
方法 | 说明 |
StringBuff append(String str) | 在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、 double、float、int、long、Object、String、StringBuff的变量 |
char charAt(int index) | 获取index位置的字符 |
int length() | 获取字符串的长度 |
int capacity() | 获取底层保存字符串空间总的大小 |
void ensureCapacity(int mininmumCapacity) | 扩容 |
void setCharAt(int index, char ch) | 将index位置的字符设置为ch |
int indexOf(String str) | 返回str第一次出现的位置 |
int indexOf(String str, int fromIndex) | 从fromIndex位置开始查找str第一次出现的位置 |
int lastIndexOf(String str) | 返回最后一次出现str的位置 |
int lastIndexOf(String str, int fromIndex) | 从fromIndex位置开始找str最后一次出现的位置 |
StringBuff insert(int offset, String str) | 在offset位置插入:八种基类类型 & String类型 & Object类型数据 |
StringBuffer deleteCharAt(int index) | 删除index位置字符 |
StringBuffer delete(int start, int end) | 删除[start, end)区间内的字符 |
StringBuffer replace(int start, int end, String str) | 将[start, end)位置的字符替换为str |
String substring(int start) | 从start开始一直到末尾的字符以String的方式返回 |
String substring(int start,int end) | 将[start, end)范围内的字符以String的方式返回 |
StringBuffer reverse() | 反转字符串 |
String toString() | 将所有字符按照String的方式返回 |
public class Main{public static void main(String[] args) {// 创建一个 StringBuffer 对象StringBuffer sb = new StringBuffer("Hello");// append 方法 - 在末尾追加内容sb.append(" World");System.out.println("After append: " + sb);// charAt 方法 - 获取指定位置的字符char ch = sb.charAt(6);System.out.println("Character at index 6: " + ch);// length 方法 - 获取字符串长度int length = sb.length();System.out.println("Length: " + length);// capacity 方法 - 获取当前容量int capacity = sb.capacity();System.out.println("Capacity: " + capacity);// ensureCapacity 方法 - 确保容量sb.ensureCapacity(50);System.out.println("Capacity after ensureCapacity: " + sb.capacity());// setCharAt 方法 - 设置指定位置的字符sb.setCharAt(0, 'h');System.out.println("After setCharAt: " + sb);// indexOf 方法 - 查找字符串第一次出现的位置int index = sb.indexOf("World");System.out.println("Index of 'World': " + index);// indexOf 方法 - 从指定位置开始查找index = sb.indexOf("o", 5);System.out.println("Index of 'o' from index 5: " + index);// lastIndexOf 方法 - 查找字符串最后一次出现的位置int lastIndex = sb.lastIndexOf("o");System.out.println("Last index of 'o': " + lastIndex);// lastIndexOf 方法 - 从指定位置开始查找最后一次出现的位置lastIndex = sb.lastIndexOf("o", 7);System.out.println("Last index of 'o' from index 7: " + lastIndex);// insert 方法 - 在指定位置插入内容sb.insert(6, "Java ");System.out.println("After insert: " + sb);// deleteCharAt 方法 - 删除指定位置的字符sb.deleteCharAt(5);System.out.println("After deleteCharAt: " + sb);// delete 方法 - 删除指定范围的字符sb.delete(6, 11);System.out.println("After delete: " + sb);// replace 方法 - 替换指定范围内的字符sb.replace(6, 11, "Universe");System.out.println("After replace: " + sb);// substring 方法 - 返回子字符串String subStr = sb.substring(6);System.out.println("Substring from index 6: " + subStr);// substring 方法 - 返回指定范围内的子字符串subStr = sb.substring(6, 14);System.out.println("Substring from index 6 to 14: " + subStr);// reverse 方法 - 反转字符串sb.reverse();System.out.println("After reverse: " + sb);// toString 方法 - 将 StringBuffer 转换为 StringString result = sb.toString();System.out.println("Final string: " + result);}
}
1.特点
(1).StringBuilder
和StringBuffer
:它们是可变的。(2).相较于String的性能更好
(3).在字符串拼接替换等场景比String更方便,实用。
2.StringBuilder
和 StringBuffer的区别
线程安全性:
StringBuilder
是非线程安全的,适用于单线程环境。StringBuffer
是线程安全的,适用于多线程环境。性能:
StringBuilder
在单线程环境中性能更高,因为它没有同步的开销。StringBuffer
由于同步机制,在多线程环境中提供线程安全,但性能会略低。使用场景:
- 在单线程环境下,使用
StringBuilder
更为合适,因其性能更优。- 在多线程环境下,使用
StringBuffer
更为合适,因其线程安全。