Java中String常用方法的高效使用技巧
1. length() 方法
length()
方法用于返回字符串的长度。它是一个非常基础且常用的方法,其实现原理相对简单。在 String
类内部,有一个 char
数组来存储字符串的字符,length()
方法实际上就是返回这个数组的长度。
示例代码如下:
public class StringLengthExample {
public static void main(String[] args) {
String str = "Hello, World!";
int length = str.length();
System.out.println("字符串的长度为: " + length);
}
}
在这个例子中,我们创建了一个字符串 Hello, World!
,然后调用 length()
方法获取其长度并打印出来。这个方法的时间复杂度是 O(1),因为它只是简单地返回内部数组的长度,不涉及任何循环或复杂的计算。
2. charAt(int index) 方法
charAt(int index)
方法用于返回指定索引位置的字符。索引从 0 开始,取值范围是 0 到 length() - 1
。如果索引超出这个范围,会抛出 StringIndexOutOfBoundsException
异常。
其实现原理也是基于内部的 char
数组,通过索引直接从数组中获取对应的字符。
示例代码:
public class StringCharAtExample {
public static void main(String[] args) {
String str = "Java";
char ch = str.charAt(2);
System.out.println("索引为2的字符是: " + ch);
}
}
在上述代码中,我们获取字符串 Java
中索引为 2 的字符并打印。这里要注意的是,在使用 charAt
方法时,一定要确保索引在有效范围内,否则程序会因为异常而终止。
3. substring(int beginIndex) 和 substring(int beginIndex, int endIndex) 方法
3.1 substring(int beginIndex)
substring(int beginIndex)
方法用于返回从指定索引 beginIndex
开始到字符串末尾的子字符串。
示例代码:
public class StringSubstring1Example {
public static void main(String[] args) {
String str = "Hello, World!";
String subStr = str.substring(7);
System.out.println("子字符串是: " + subStr);
}
}
在这个例子中,我们从索引 7 开始截取字符串,得到子字符串 World!
。
3.2 substring(int beginIndex, int endIndex)
substring(int beginIndex, int endIndex)
方法用于返回从 beginIndex
开始(包括)到 endIndex
结束(不包括)的子字符串。
示例代码:
public class StringSubstring2Example {
public static void main(String[] args) {
String str = "Hello, World!";
String subStr = str.substring(0, 5);
System.out.println("子字符串是: " + subStr);
}
}
这里从索引 0 开始截取到索引 5 之前(不包括 5),得到子字符串 Hello
。需要注意的是,beginIndex
必须小于等于 endIndex
,且 endIndex
不能超过字符串的长度,否则会抛出 StringIndexOutOfBoundsException
异常。
在 String
类的实现中,substring
方法并没有创建一个全新的字符数组来存储子字符串的内容,而是通过共享原字符串的 char
数组,并设置不同的偏移量和长度来实现子字符串的表示。这在一定程度上节省了内存,但也可能会导致一些潜在的问题,比如原字符串被垃圾回收时,子字符串可能还在使用,从而影响性能。从 Java 7u6 开始,substring
方法的实现进行了优化,不再共享原数组,而是创建一个新的数组来存储子字符串,避免了这种潜在的性能问题。
4. equals(Object obj) 和 equalsIgnoreCase(String anotherString) 方法
4.1 equals(Object obj)
equals(Object obj)
方法用于比较两个字符串的内容是否相等。它会先判断传入的对象是否为 String
类型,如果不是则直接返回 false
。如果是 String
类型,再逐个字符地比较两个字符串的内容。
示例代码:
public class StringEqualsExample {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
String str3 = "hello";
boolean isEqual1 = str1.equals(str2);
boolean isEqual2 = str1.equals(str3);
System.out.println("str1 和 str2 是否相等: " + isEqual1);
System.out.println("str1 和 str3 是否相等: " + isEqual2);
}
}
在上述代码中,str1
和 str2
内容相同,equals
方法返回 true
;而 str1
和 str3
虽然字符相同但大小写不同,equals
方法返回 false
。
4.2 equalsIgnoreCase(String anotherString)
equalsIgnoreCase(String anotherString)
方法与 equals
方法类似,只是它在比较时忽略大小写。
示例代码:
public class StringEqualsIgnoreCaseExample {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "hello";
boolean isEqual = str1.equalsIgnoreCase(str2);
System.out.println("str1 和 str2 是否相等(忽略大小写): " + isEqual);
}
}
这里 str1
和 str2
虽然大小写不同,但 equalsIgnoreCase
方法返回 true
。在实现上,equalsIgnoreCase
方法会将两个字符串中的字符统一转换为大写或小写后再进行比较。
5. compareTo(String anotherString) 和 compareToIgnoreCase(String str) 方法
5.1 compareTo(String anotherString)
compareTo(String anotherString)
方法用于按字典顺序比较两个字符串。它返回一个整数值,如果当前字符串小于 anotherString
,返回负整数;如果相等,返回 0;如果当前字符串大于 anotherString
,返回正整数。
示例代码:
public class StringCompareToExample {
public static void main(String[] args) {
String str1 = "apple";
String str2 = "banana";
String str3 = "apple";
int result1 = str1.compareTo(str2);
int result2 = str1.compareTo(str3);
System.out.println("str1 与 str2 的比较结果: " + result1);
System.out.println("str1 与 str3 的比较结果: " + result2);
}
}
在这个例子中,由于 apple
在字典顺序上小于 banana
,compareTo
方法返回一个负整数;而 str1
和 str3
内容相同,返回 0。
5.2 compareToIgnoreCase(String str)
compareToIgnoreCase(String str)
方法与 compareTo
方法类似,只是在比较时忽略大小写。
示例代码:
public class StringCompareToIgnoreCaseExample {
public static void main(String[] args) {
String str1 = "Apple";
String str2 = "apple";
int result = str1.compareToIgnoreCase(str2);
System.out.println("str1 与 str2 的比较结果(忽略大小写): " + result);
}
}
这里 str1
和 str2
虽然大小写不同,但忽略大小写后内容相同,compareToIgnoreCase
方法返回 0。
6. indexOf(int ch) 和 indexOf(String str) 方法
6.1 indexOf(int ch)
indexOf(int ch)
方法用于返回指定字符 ch
在字符串中第一次出现的索引位置。如果不存在该字符,则返回 -1。
示例代码:
public class StringIndexOfCharExample {
public static void main(String[] args) {
String str = "Hello, World!";
int index = str.indexOf('o');
System.out.println("字符 'o' 第一次出现的索引位置: " + index);
}
}
在上述代码中,字符 o
第一次出现在索引 4 的位置。
6.2 indexOf(String str)
indexOf(String str)
方法用于返回指定子字符串 str
在字符串中第一次出现的索引位置。如果不存在该子字符串,则返回 -1。
示例代码:
public class StringIndexOfStringExample {
public static void main(String[] args) {
String str = "Hello, World!";
int index = str.indexOf("World");
System.out.println("子字符串 'World' 第一次出现的索引位置: " + index);
}
}
这里子字符串 World
第一次出现在索引 7 的位置。这两个方法都是从字符串的开头开始查找,实现时采用了简单的线性查找算法,时间复杂度为 O(n),其中 n 是字符串的长度。
7. lastIndexOf(int ch) 和 lastIndexOf(String str) 方法
7.1 lastIndexOf(int ch)
lastIndexOf(int ch)
方法用于返回指定字符 ch
在字符串中最后一次出现的索引位置。如果不存在该字符,则返回 -1。与 indexOf(int ch)
方法不同的是,它是从字符串的末尾开始向前查找。
示例代码:
public class StringLastIndexOfCharExample {
public static void main(String[] args) {
String str = "Hello, World!";
int index = str.lastIndexOf('o');
System.out.println("字符 'o' 最后一次出现的索引位置: " + index);
}
}
在这个例子中,字符 o
最后一次出现在索引 8 的位置。
7.2 lastIndexOf(String str)
lastIndexOf(String str)
方法用于返回指定子字符串 str
在字符串中最后一次出现的索引位置。如果不存在该子字符串,则返回 -1。同样是从字符串的末尾开始向前查找。
示例代码:
public class StringLastIndexOfStringExample {
public static void main(String[] args) {
String str = "Hello, World! Hello, Java!";
int index = str.lastIndexOf("Hello");
System.out.println("子字符串 'Hello' 最后一次出现的索引位置: " + index);
}
}
这里子字符串 Hello
最后一次出现在索引 13 的位置。这两个方法同样采用线性查找算法,时间复杂度为 O(n)。
8. contains(CharSequence s) 方法
contains(CharSequence s)
方法用于判断当前字符串是否包含指定的字符序列 s
。它实际上是通过调用 indexOf
方法来实现的,如果 indexOf
方法返回的索引不是 -1,则表示包含该字符序列,返回 true
,否则返回 false
。
示例代码:
public class StringContainsExample {
public static void main(String[] args) {
String str = "Hello, World!";
boolean contains = str.contains("World");
System.out.println("字符串是否包含 'World': " + contains);
}
}
在上述代码中,字符串 Hello, World!
包含子字符串 World
,所以 contains
方法返回 true
。
9. replace(char oldChar, char newChar) 和 replace(CharSequence target, CharSequence replacement) 方法
9.1 replace(char oldChar, char newChar)
replace(char oldChar, char newChar)
方法用于将字符串中所有的 oldChar
替换为 newChar
,并返回一个新的字符串。原字符串并不会被修改,因为 String
类是不可变的。
示例代码:
public class StringReplaceCharExample {
public static void main(String[] args) {
String str = "Hello, World!";
String newStr = str.replace('o', '0');
System.out.println("替换后的字符串: " + newStr);
}
}
在这个例子中,我们将字符串中的 o
替换为 0
,得到新字符串 Hell0, W0rld!
。
9.2 replace(CharSequence target, CharSequence replacement)
replace(CharSequence target, CharSequence replacement)
方法用于将字符串中所有的 target
子字符串替换为 replacement
子字符串,并返回一个新的字符串。
示例代码:
public class StringReplaceStringExample {
public static void main(String[] args) {
String str = "Hello, World!";
String newStr = str.replace("World", "Java");
System.out.println("替换后的字符串: " + newStr);
}
}
这里将 World
替换为 Java
,得到新字符串 Hello, Java!
。这两个 replace
方法在实现时,会遍历原字符串,根据需要替换的字符或子字符串进行替换操作,然后构建一个新的字符串返回。
10. split(String regex) 和 split(String regex, int limit) 方法
10.1 split(String regex)
split(String regex)
方法用于根据指定的正则表达式 regex
将字符串拆分为字符串数组。
示例代码:
public class StringSplitExample1 {
public static void main(String[] args) {
String str = "apple,banana,orange";
String[] parts = str.split(",");
for (String part : parts) {
System.out.println(part);
}
}
}
在上述代码中,我们以逗号 ,
作为分隔符,将字符串拆分为三个部分并打印出来。
10.2 split(String regex, int limit)
split(String regex, int limit)
方法与 split(String regex)
方法类似,但它可以指定拆分的最大次数 limit
。如果 limit
大于 0,最多拆分 limit - 1
次,数组的长度不会超过 limit
,并且数组的最后一个元素会包含剩余的所有字符;如果 limit
为 0,会尽可能多地拆分,并且丢弃末尾的空字符串;如果 limit
为负数,会尽可能多地拆分,并且保留末尾的空字符串。
示例代码:
public class StringSplitExample2 {
public static void main(String[] args) {
String str = "apple,banana,orange";
String[] parts1 = str.split(",", 2);
String[] parts2 = str.split(",", 0);
String[] parts3 = str.split(",", -1);
System.out.println("limit 为 2 时的拆分结果:");
for (String part : parts1) {
System.out.println(part);
}
System.out.println("limit 为 0 时的拆分结果:");
for (String part : parts2) {
System.out.println(part);
}
System.out.println("limit 为 -1 时的拆分结果:");
for (String part : parts3) {
System.out.println(part);
}
}
}
在这个例子中,limit
为 2 时,只拆分一次,得到两个元素的数组;limit
为 0 时,丢弃末尾可能的空字符串;limit
为 -1 时,保留末尾的空字符串。
11. toUpperCase() 和 toLowerCase() 方法
11.1 toUpperCase()
toUpperCase()
方法用于将字符串中的所有字符转换为大写形式,并返回一个新的字符串。
示例代码:
public class StringToUpperCaseExample {
public static void main(String[] args) {
String str = "hello, world!";
String upperStr = str.toUpperCase();
System.out.println("转换为大写后的字符串: " + upperStr);
}
}
这里将字符串 hello, world!
转换为 HELLO, WORLD!
。
11.2 toLowerCase()
toLowerCase()
方法用于将字符串中的所有字符转换为小写形式,并返回一个新的字符串。
示例代码:
public class StringToLowerCaseExample {
public static void main(String[] args) {
String str = "HELLO, WORLD!";
String lowerStr = str.toLowerCase();
System.out.println("转换为小写后的字符串: " + lowerStr);
}
}
此例中,将字符串 HELLO, WORLD!
转换为 hello, world!
。这两个方法在实现时,会根据字符的 Unicode 编码规则进行大小写转换。
12. trim() 方法
trim()
方法用于去除字符串两端的空白字符(包括空格、制表符、换行符等),并返回一个新的字符串。
示例代码:
public class StringTrimExample {
public static void main(String[] args) {
String str = " Hello, World! ";
String trimmedStr = str.trim();
System.out.println("去除两端空白后的字符串: " + trimmedStr);
}
}
在上述代码中,将字符串两端的空白字符去除,得到 Hello, World!
。trim
方法的实现是通过扫描字符串的两端,找到第一个和最后一个非空白字符的位置,然后截取这两个位置之间的字符形成新的字符串。
13. join(CharSequence delimiter, CharSequence... elements) 方法
join(CharSequence delimiter, CharSequence... elements)
方法是 Java 8 引入的静态方法,用于将多个字符序列用指定的分隔符连接起来,形成一个新的字符串。
示例代码:
public class StringJoinExample {
public static void main(String[] args) {
String result = String.join(", ", "apple", "banana", "orange");
System.out.println("连接后的字符串: " + result);
}
}
在这个例子中,我们使用逗号和空格作为分隔符,将 apple
、banana
和 orange
连接起来,得到 apple, banana, orange
。该方法的实现原理是通过 StringBuilder
类来构建最终的字符串,这样可以提高连接操作的效率,避免了使用 +
运算符在循环中连接字符串可能导致的性能问题。
14. format(String format, Object... args) 方法
format(String format, Object... args)
方法用于使用指定的格式字符串和参数来格式化字符串,返回一个格式化后的新字符串。它类似于 C 语言中的 printf
函数。
示例代码:
public class StringFormatExample {
public static void main(String[] args) {
String name = "Alice";
int age = 30;
String message = String.format("姓名:%s,年龄:%d", name, age);
System.out.println("格式化后的字符串: " + message);
}
}
在上述代码中,我们使用 %s
表示字符串类型的参数,%d
表示整数类型的参数,将 name
和 age
按照指定格式插入到字符串中,得到 姓名:Alice,年龄:30
。格式字符串中的占位符还有很多,如 %f
用于浮点数,%c
用于字符等,可以根据实际需求灵活使用。
15. intern() 方法
intern()
方法用于将字符串对象添加到字符串常量池中。如果字符串常量池中已经存在相同内容的字符串,则返回常量池中的字符串;否则,将当前字符串添加到常量池,并返回该字符串。
示例代码:
public class StringInternExample {
public static void main(String[] args) {
String str1 = new String("Hello");
String str2 = str1.intern();
String str3 = "Hello";
System.out.println(str1 == str2); // false
System.out.println(str2 == str3); // true
}
}
在这个例子中,str1
是通过 new
关键字创建的字符串对象,在堆内存中;调用 intern()
方法后,str2
指向了字符串常量池中的 Hello
字符串;str3
直接指向字符串常量池中的 Hello
字符串。所以 str1
和 str2
不相等(因为它们指向不同的内存位置),而 str2
和 str3
相等。使用 intern()
方法可以在一定程度上节省内存,特别是在处理大量重复字符串时,但需要注意它可能带来的性能开销,因为字符串常量池的维护也需要一定的资源。
通过深入了解这些 String
常用方法的本质和高效使用技巧,我们在实际编程中可以更加灵活、高效地处理字符串相关的操作,提高程序的性能和可读性。同时,在使用这些方法时,要根据具体的场景和需求进行合理选择,避免因不当使用而导致的性能问题或逻辑错误。例如,在处理大量字符串连接操作时,应优先考虑使用 StringBuilder
或 StringBuffer
类,而不是频繁使用 +
运算符或 concat
方法;在进行字符串比较时,要明确是需要严格区分大小写还是忽略大小写等。总之,对这些方法的熟练掌握和合理运用是 Java 编程中处理字符串的关键。