理论知识:
1. String 的不可变性与常量池机制
- 不可变性:
String
对象一旦创建,其值无法更改。每次对字符串进行修改操作(如拼接、替换等)都会创建一个新的String
对象。
public class StringImmutability {
public static void main(String[] args) {
String str1 = "hello";
String str2 = str1.concat(" world");
System.out.println("原始字符串: " + str1); // 输出: hello
System.out.println("新字符串: " + str2); // 输出: hello world
}
}
- 常量池机制:
- Java 在常量池中缓存字符串字面量。对于相同内容的字符串字面量,只会在内存中存储一个实例。
public class StringPoolExample {
public static void main(String[] args) {
String str1 = "java";
String str2 = "java";
String str3 = new String("java");
System.out.println(str1 == str2); // 输出: true(指向同一个常量池对象)
System.out.println(str1 == str3); // 输出: false(指向堆中的新对象)
}
}
2. StringBuilder 和 StringBuffer 的区别
- StringBuilder:
- 线程不安全,但性能较高,适用于单线程环境。
- StringBuffer:
- 线程安全,但性能稍低,适用于多线程环境。
public class StringBuilderVsStringBuffer {
public static void main(String[] args) {
long startTime, endTime;
// StringBuilder 性能测试
startTime = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
sb.append("a");
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder耗时: " + (endTime - startTime) + "ms");
// StringBuffer 性能测试
startTime = System.currentTimeMillis();
StringBuffer sbf = new StringBuffer();
for (int i = 0; i < 100000; i++) {
sbf.append("a");
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer耗时: " + (endTime - startTime) + "ms");
}
}
3. 常用字符串操作方法
- 拼接:
concat()
:直接连接两个字符串。+
运算符:语法简洁,底层会自动使用StringBuilder
。
public class StringConcatenation {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "World";
// 使用concat方法
String result1 = str1.concat(" ").concat(str2);
System.out.println("使用concat: " + result1);
// 使用+运算符
String result2 = str1 + " " + str2;
System.out.println("使用+运算符: " + result2);
}
}
- 替换:
replace()
:替换字符或子字符串。
public class StringReplaceExample {
public static void main(String[] args) {
String str = "apple, banana, cherry";
// 替换所有逗号为分号
String replacedStr = str.replace(",", ";");
System.out.println("替换后的字符串: " + replacedStr);
}
}
- 查找与分割:
indexOf()
:查找子字符串的位置。split()
:按照指定分隔符拆分字符串。
public class StringSearchAndSplit {
public static void main(String[] args) {
String str = "Java is fun. Java is powerful.";
// 查找子字符串的位置
int index = str.indexOf("Java");
System.out.println("第一次出现'Java'的位置: " + index);
// 按空格分割字符串
String[] words = str.split(" ");
System.out.println("分割后的字符串数组:");
for (String word : words) {
System.out.println(word);
}
}
}
实践操作:字符串工具类
目标功能
- 统计字符串中每个字符的出现次数。
- 反转字符串。
- 替换指定字符。
代码实现
import java.util.HashMap;
import java.util.Map;
public class StringUtil {
// 1. 统计字符出现次数
public static Map<Character, Integer> countCharacterOccurrences(String str) {
Map<Character, Integer> charCountMap = new HashMap<>();
for (char c : str.toCharArray()) {
charCountMap.put(c, charCountMap.getOrDefault(c, 0) + 1);
}
return charCountMap;
}
// 2. 反转字符串
public static String reverseString(String str) {
return new StringBuilder(str).reverse().toString();
}
// 3. 替换指定字符
public static String replaceCharacter(String str, char oldChar, char newChar) {
return str.replace(oldChar, newChar);
}
public static void main(String[] args) {
String testString = "hello world";
// 统计字符出现次数
Map<Character, Integer> charCount = countCharacterOccurrences(testString);
System.out.println("字符出现次数: " + charCount);
// 字符串反转
String reversed = reverseString(testString);
System.out.println("反转后的字符串: " + reversed);
// 替换指定字符
String replacedString = replaceCharacter(testString, 'o', 'x');
System.out.println("替换后的字符串: " + replacedString);
}
}
public class Test {
public static void main(String[] args) {
/**
* 这里给一个英语单词翻转的,这也是编程题的一道题。这个更多的时考察输入这部分吧
* 例子输入:
* 给定一句英语句子,每个单词之间可以有多个空格。句子首尾也可以有多个空格
* | apple an is this |
* 输出:
* 翻转单词,去除多余的空格
* |this is an apple|
*/
String str = "apple an is this";
String[] strs = str.split(" ");
Object[] array = Arrays.stream(strs).toArray();
for (int i = 0; i < array.length / 2; i++) {
Object temp = array[i];
array[i] = array[array.length - 1 - i];
array[array.length - 1 - i] = temp;
}
String result = "";
for (int i = 0; i < array.length; i++) {
result += array[i] + " ";
}
System.out.println(result);
}
}
工作中的使用场景
- 日志分析:统计日志文件中字符、单词的出现次数。
- 数据清洗:批量替换字符串中的特定字符或格式化数据。
- 性能优化:在大量拼接操作中使用
StringBuilder
替代String
。
总结
本文深入探讨了 Java 中字符串操作的相关知识和实践。首先,分析了 String
的不可变性及其在常量池中的优化机制,帮助开发者理解为什么 String
在内存中高效且安全。接着,对比了 StringBuilder
和 StringBuffer
,明确它们在单线程和多线程环境中的适用场景。然后,重点介绍了字符串的常用操作方法,如拼接、替换、查找与分割,并通过具体代码演示了它们的应用。最后,通过实践编写一个字符串工具类,将理论知识转化为实用功能,解决字符统计、字符串反转和字符替换等实际问题。这些知识在工作中能有效提高代码的性能和可读性。