目 录
[3. 相关方法](#3. 相关方法)
[(1)replace(CharSequence target, CharSequence replacement)](#(1)replace(CharSequence target, CharSequence replacement))
[(2)replaceAll(String regex, CharSequence replacement)](#(2)replaceAll(String regex, CharSequence replacement))
[(3)split(String regex)](#(3)split(String regex))
[(4)matches(String regex)](#(4)matches(String regex))
[1.统计字符串中 大小写字母、数字个数](#1.统计字符串中 大小写字母、数字个数)
[四、StringBuffer 与 StringBuilder](#四、StringBuffer 与 StringBuilder)
[2.StringBuilder 常用方法](#2.StringBuilder 常用方法)
[(1)append(Type date)](#(1)append(Type date))
[(2)delete(int start, int end)](#(2)delete(int start, int end))
[(3)deleteCharAt(int index)](#(3)deleteCharAt(int index))
[(4)insert(int offset, String str)](#(4)insert(int offset, String str))
[(5)replace(int start, int end, String str)](#(5)replace(int start, int end, String str))
[(7)setCharAt(int index, char ch)](#(7)setCharAt(int index, char ch))
[(8)setLength(int newLength)](#(8)setLength(int newLength))
一、正则表达式
1.说明
- Java、C 等大部分编程语言都支持正则表达式;
- 一种用于描述特定模式的表达式,可以匹配、查找、替换文本中与该模式匹配的内容;
- regular expression ,简称 regex 或 regexp 。
2.应用
- 验证输入内容格式是否合规;
- 文本编辑器中的查找和替换;
- 数据挖掘和信息提取;
- 编写 awk、sed、grep 等脚本语言;
- 处理数据和字符串时性能较高,可在开发 Web 应用程序时使用。
3. 相关方法
(1)replace(CharSequence target, CharSequence replacement)
将当前字符串中所有的 target 替换为 replacement ,并返回一个新的字符串。
java
public class StringTest {
public static void main(String[] args) {
String str = "使一个人的有限的生命,更加有效,也即等于延长了人的生命。".replace("生命", "life");
System.out.println(str); // 输出:使一个人的有限的life,更加有效,也即等于延长了人的life。
}
}
(2)replaceAll(String regex, CharSequence replacement)
将当前字符串中所有符合规则的正则表达式的 regex 替换为 replacement 。
java
public class StringTest {
public static void main(String[] args) {
// 将字符串中的数字替换为空格
String str = "q1w2e3r4t5y6u7?!~".replaceAll("\\d", " ");
System.out.println(str); // 输出:q w e r t y u ?!~
}
}
(3)split(String regex)
将当前字符串以某个正则表达式表示的子字符串进行分割,并返回一个子字符串数组。
java
public class StringTest {
public static void main(String[] args) {
String str = "1945-08-15";
String[] arr = str.split("-");
System.out.print("日本无条件投降:");
for (String s : arr) {
System.out.print(s + " ");
}
// 输出:日本无条件投降:1945 08 15
}
}
(4)matches(String regex)
判断当前字符串是否符合正则表达式 regex 。
java
public class StringTest {
public static void main(String[] args) {
String email = "1233953804@qq.com";
// 正则表达式
String emailReg = "^[A-Za-z0-9\\u4e00-\\u9fa5]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";
// 判断是否匹配
System.out.println(email.matches(emailReg)); // 输出:true
}
}
二、常见问题
1.字符串比较
(1)问题1
java
public class StringTest {
public static void main(String[] args) {
String s1 = "abc";
String s2 = new String(s1);
System.out.println(s1 == s2); // false
System.out.println(s1.equals(s2)); // true
}
}
(2)问题2
java
public class StringTest {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "a" + "b" + "c";
System.out.println(s1 == s2); // true
System.out.println(s1.equals(s2)); // true
// 因为编译阶段就完成初始化
}
}
(3)问题3
java
public class StringTest {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "a";
String s3 = s2 + "bc";
System.out.println(s1 == s3); // false
System.out.println(s1.equals(s3)); // true
}
}
(4)问题4
java
public class StringTest {
public static void main(String[] args) {
String s1 = "ab";
final String s2 = "b";
String s3 = "a" + s2;
System.out.println(s1 == s3); // true
System.out.println(s1.equals(s3)); // true
}
}
(5)问题5
java
public class StringTest {
public static void main(String[] args) {
String s1 = "ab";
final String s2 = getB(); // 运行时赋值
String s3 = "a" + s2;
System.out.println(s1 == s3); // false
System.out.println(s1.equals(s3)); // true
}
private static String getB() {
return "b";
}
}
(6)问题6
java
public class StringTest {
public static void main(String[] args) {
String s1 = "a3";
String s2 = "a" + 3;
System.out.println(s1 == s2); // true
System.out.println(s1.equals(s2)); // true
}
}
(7)问题7
java
public class StringTest {
public static void main(String[] args) {
String s1 = new String("abc");
StringBuilder s2 = new StringBuilder("abc");
System.out.println(s1.equals(s2)); // false
// 因为两者类型不一致,所以无法比较
}
}
2.创建对象个数
(1)问题1
java
public class StringTest {
public static void main(String[] args) {
// 字符串常量池 1 个
String s1 = "a";
// 字符串常量池 1 个,堆中 1 个
String s2 = new String("b");
// 堆中 2 个,其中一个 StringBuilder 对象,一个 String 对象
String s3 = s1 + s2;
// 一共 5 个对象,堆中 3 个,常量池 2 个
}
}
(2)问题2
java
public class StringTest {
public static void main(String[] args) {
// 字符串常量池 2 个
// StringBuilder 1 个
// 堆中Stringr 3 个
String s = new String("a") + new String("b");
// 一共 6 个对象
}
}
3.空指针异常
java
public class StringTest {
public static void main(String[] args) {
String s1 = null;
String s2 = s1 + null;
System.out.println(s2); // nullnull
// 不会出现空指针异常,因为底层会调用 valueOf 方法
}
}
三、实例
1.统计字符串中 大小写字母、数字个数
java
public class StringTest {
public static void main(String[] args) {
String str = "I am 123 , I Like World 521 .";
char[] chars = str.toCharArray();
int bigCount = 0, smallCount = 0, numberCount = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i] >= 'A' && chars[i] <= 'Z') {
bigCount++;
}
if (chars[i] >= 'a' && chars[i] <= 'z') {
smallCount++;
}
if (chars[i] >= '0' && chars[i] <= '9') {
numberCount++;
}
}
System.out.println("大写字母个数:" + bigCount); // 大写字母个数:4
System.out.println("小写字母个数:" + smallCount); // 小写字母个数:9
System.out.println("数字个数:" + numberCount); // 数字个数:6
}
}
2.反转字符串
java
public class StringTest {
public static void main(String[] args) {
String str = "I like you";
char[] chars = str.toCharArray();
for (int i = 0; i < chars.length / 2; i++) {
char temp = chars[i];
chars[i] = chars[chars.length - 1 - i];
chars[chars.length - 1 - i] = temp;
}
System.out.println(new String(chars)); // uoy ekil I
}
}
3.统计子字符串出现次数
java
public class StringTest {
public static void main(String[] args) {
String str = "ABCDAAD";
int count = 0, index = 0;
while ((index = str.indexOf("A")) != -1) {
str = str.substring(index + 1);
count++;
}
System.out.println(count); // 3
}
}
4.身份证号信息抽取
java
public class StringTest {
public static void main(String[] args) {
String id = "140211202502021224";
System.out.println("出生年份:" + id.substring(6, 10)); // 出生年份:2025
System.out.println("出生月份:" + id.substring(10, 12)); // 出生月份:02
System.out.println("出生日期:" + id.substring(12, 14)); // 出生日期:02
System.out.println("性别:" + (id.charAt(16) % 2 == 0 ? "女" : "男")); // 性别:女
}
}
5.获取两个字符串中最大相同子串
java
public class StringTest {
public static void main(String[] args) {
String s1 = "abcdefghijklmnopqrstuvwxyz";
String s2 = "123abcdefghhhjjjkkklll";
int maxLen = 0, start = 0;
for (int i = 0; i < s1.length(); i++) {
for (int j = 0; j < s2.length(); j++) {
int sameLen = 0;
while (i + sameLen < s1.length() && j + sameLen < s2.length() && s1.charAt(i + sameLen) == s2.charAt(j + sameLen)) {
sameLen++;
}
if (sameLen > maxLen) {
maxLen = sameLen;
start = i;
}
}
}
System.out.println(s1.substring(start, start + maxLen)); // 输出:abcdefgh
}
}
四、StringBuffer 与 StringBuilder
1.说明
可变长度字符串;
目的是应对频繁进行字符串拼接;
jdk 5 新增 StringBuilder ;
StringBuffer 线程安全,在不考虑线程安全情况下优先选择 StringBuilder ,效率更高;
在底层是 byte 数组,且没有被 final 修饰。若数组存满,可以创建一个更大的新数组实现扩容,重新指向新数组对象;
优化:在创建 StringBuilder 对象时,预估字符串长度,给定合适的初始化容量,减少底层数组的扩容;
StringBuilder 默认初始化容量为 16 ;
StringBuilder 扩容策略:从当前容量开始,每次扩容为原来的 2 倍再加 2 。
2.StringBuilder 常用方法
(1)append(Type date)
java
public class StringTest {
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Hello");
stringBuilder.append('a');
stringBuilder.append(99);
stringBuilder.append(true);
stringBuilder.append(new Object());
System.out.println(stringBuilder); // 输出:Helloa99truejava.lang.Object@4eec7777
}
}
(2)delete(int start, int end)
java
public class StringTest {
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Hello");
stringBuilder.append('a');
stringBuilder.append(99);
stringBuilder.append(true);
stringBuilder.append(new Object());
System.out.println(stringBuilder); // 输出:Helloa99truejava.lang.Object@4eec7777
stringBuilder.delete(2, 6);
System.out.println(stringBuilder); // 输出:He99truejava.lang.Object@4eec7777
}
}
(3)deleteCharAt(int index)
java
public class StringTest {
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Hello");
stringBuilder.append('a');
stringBuilder.append(99);
stringBuilder.append(true);
stringBuilder.append(new Object());
System.out.println(stringBuilder); // 输出:Helloa99truejava.lang.Object@4eec7777
stringBuilder.deleteCharAt(3);
System.out.println(stringBuilder); // 输出:Heloa99truejava.lang.Object@4eec7777
}
}
(4)insert(int offset, String str)
java
public class StringTest {
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Hello");
stringBuilder.append('a');
stringBuilder.append(99);
stringBuilder.append(true);
stringBuilder.append(new Object());
System.out.println(stringBuilder); // 输出:Helloa99truejava.lang.Object@4eec7777
stringBuilder.insert(5, "World");
System.out.println(stringBuilder); // 输出:HelloWorlda99truejava.lang.Object@4eec7777
}
}
(5)replace(int start, int end, String str)
java
public class StringTest {
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Hello");
stringBuilder.append('a');
stringBuilder.append(99);
stringBuilder.append(true);
stringBuilder.append(new Object());
System.out.println(stringBuilder); // 输出:Helloa99truejava.lang.Object@4eec7777
stringBuilder.replace(8, 15, "StringBuilder~");
System.out.println(stringBuilder); // 输出:Helloa99StringBuilder~a.lang.Object@4eec7777
}
}
(6)reverse()
java
public class StringTest {
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Hello");
stringBuilder.append('a');
stringBuilder.append(99);
stringBuilder.append(true);
stringBuilder.append(new Object());
System.out.println(stringBuilder); // 输出:Helloa99truejava.lang.Object@4eec7777
stringBuilder.reverse();
System.out.println(stringBuilder); // 输出:7777cee4@tcejbO.gnal.avajeurt99aolleH
}
}
(7)setCharAt(int index, char ch)
java
public class StringTest {
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Hello");
stringBuilder.append('a');
stringBuilder.append(99);
stringBuilder.append(true);
stringBuilder.append(new Object());
System.out.println(stringBuilder); // 输出:Helloa99truejava.lang.Object@4eec7777
stringBuilder.setCharAt(0, '5');
System.out.println(stringBuilder); // 输出:5elloa99truejava.lang.Object@4eec7777
}
}
(8)setLength(int newLength)
java
public class StringTest {
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Hello");
stringBuilder.append('a');
stringBuilder.append(99);
stringBuilder.append(true);
stringBuilder.append(new Object());
System.out.println(stringBuilder); // 输出:Helloa99truejava.lang.Object@4eec7777
stringBuilder.setLength(5);
System.out.println(stringBuilder); // 输出:Hello
}
}
3.效率
(1)String
java
public class StringTest {
public static void main(String[] args) {
long start = System.currentTimeMillis();
String s = "";
for (int i = 0; i < 100000; i++) {
s += i;
}
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start) + "毫秒"); // 耗时:3347毫秒
}
}
(2)StringBuilder
java
public class StringTest {
public static void main(String[] args) {
long start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder(100000);
for (int i = 0; i < 100000; i++) {
sb.append(i);
}
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start) + "毫秒"); // 耗时:8毫秒
}
}
(3)StringBuffer
java
public class StringTest {
public static void main(String[] args) {
long start = System.currentTimeMillis();
StringBuffer sb = new StringBuffer(100000);
for (int i = 0; i < 100000; i++) {
sb.append(i);
}
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start) + "毫秒"); // 耗时:8毫秒
}
}
(4)说明
String 拼接中,底层会新建一个 StringBuilder 对象,调用其 append()方法进行追加。之后在调用 StringBuilder 的 toString()方法转换为 String 类型,会导致频繁创建 String 对象,效率极低,同时 GC 也面临巨大负荷。