目 录
一、正则表达式
1.说明
2.应用
3. 相关方法
(1)replace(CharSequence target, CharSequence replacement)
(2)replaceAll(String regex, CharSequence replacement)
(3)split(String regex)
(4)matches(String regex)
二、常见问题
1.字符串比较
(1)问题1
(2)问题2
(3)问题3
(4)问题4
(5)问题5
(6)问题6
(7)问题7
2.创建对象个数
(1)问题1
(2)问题2
3.空指针异常
三、实例
1.统计字符串中 大小写字母、数字个数
2.反转字符串
3.统计子字符串出现次数
4.身份证号信息抽取
5.获取两个字符串中最大相同子串
四、StringBuffer 与 StringBuilder
1.说明
2.StringBuilder 常用方法
(1)append(Type date)
(2)delete(int start, int end)
(3)deleteCharAt(int index)
(4)insert(int offset, String str)
(5)replace(int start, int end, String str)
(6)reverse()
(7)setCharAt(int index, char ch)
(8)setLength(int newLength)
3.效率
(1)String
(2)StringBuilder
(3)StringBuffer
(4)说明
一、正则表达式
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 也面临巨大负荷。