开发Java后端Java - 字符串
MelodyJava 字符串
1. 字符串的创建

1 2 3 4 5 6 7 8 9 10
| String str = "字符串";
String str = new String("字符串");
char[] ch = {'字', '符', '串'}; String str = new String(ch);
byte[] bytes = {97, 98, 99}; String str = new String(bytes);
|
1.1 字符串的内存模型

在上述图中,当使用双引号直接赋值时,在栈内存中main
方法执行了String s1 = "abc"
,JVM会先检查在堆内存
中的字符串常量池
有没有”abc”
这个字符串,如果没有就会生成一个abc
存放到字符串常量池
中,并把地址值
赋值给s1
,在s2
创建时,由于abc
已经在字符串常量池
中存在,所以会直接把地址值
赋值给s2

在上述图中,使用了字符数组
的方式来创建字符串对象,由于字符数组
是引用数据类型
它执行后会在堆内存
中开辟一个空间,并将地址
返回给chs
,当s1
创建时传入chs
的地址值
,它会对在堆内存
中存储的字符数组
生成一个全新的
String
对象并将地址
返回给s1
,s2
的创建重复刚才的步骤,但s2
的指向的字符串对象
跟s1指向的不一致,这个过程不会有地址值复用
1.2 字符串的常用方法
1.2.1 比较
1 2 3 4 5 6 7
| String s1 = new String("abc"); String s2 = new String("abc"); if (s1 == s2) { System.out.println("相等"); } else { System.out.println("不相等"); }
|
1 2 3 4 5 6 7
| String s3 = "abc"; String s4 = "abc"; if (s3 == s4) { System.out.println("相等"); } else { System.out.println("不相等"); }
|
观察两个代码块可以发现,通过new
出来的String
对象,它会在堆内存
中将字符串
进行存储,从而分配两个不同的地址值
分别赋值给 s1和s2变量,在控制语句中实际上是判断的地址值是否相等,因为在堆内存
中是两个不同的地址,使用会输出不相等。
而第二个通过引号直接赋值的方式产生的String
对象,它会将字符串
存储到字符串常量池
中,因为两次通过引号赋值是同一个字符串
,所以s3和s4对象是被赋值同一个地址值
,最后在控制语句中输出相等。
1.2.2 常用API
1 2 3 4 5 6 7 8 9 10 11
| public int length() public char charAt(int index) public char[] toCharArray() public boolean equals(Object anObject) public boolean equalsIgnoreCase(String anotherString) public String substring(int beginIndex, int endIndex) public String substring(int beginIndex) public String replace(CharSequence target, CharSequence replacement) public boolean contains(CharSequence s) public boolean startsWith(String prefix) public String[] split(String regex)
|
1 2 3 4 5 6
| StringBuilder builder = new StringBuilder(); public StringBuilder append(String str) public int length() public String toString() public StringBuilder reverse()
|
1 2
| StringJoiner joiner = new StringJoiner("分割符","开始符号","结束符号"); public StringJoiner add(charSequence charsequence)
|
1.3 字符串原理小结
1.3.1 字符串存储的原理
- 直接
赋值
会复用字符串常量池中的
new
出来不会复用,而是开辟一个新的空间
1.3.2 ==号比较的到底是什么
1.3.3 字符串拼接的底层原理
- 如果没有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果,会复用
字符串常量池
- 如果有变量参与,会创建新的字符串对象,浪费内存
1.3.4 StringBuilder提高效率原理
- 所有要拼接的内容都会往
StringBuilder
中放,不会创建很多无用的空间,节约内存
1.3.5 StringBuilder扩容机制
- 默认创建一个长度为16的
字节数组
- 添加的内容长度小于16,直接存储
- 添加的内容大于16会扩容(原来的容量 * 2 + 2)
- 如果扩容之后还不够,以实际长度为准
1.4 案例
已知正确的用户名和密码,请用程序实现模拟用户登录
总共给三次机会,登录之后给出相应的提示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
public static void main(String[] args) { String username = "zhangsan"; String password = "123456"; Scanner sc = new Scanner(System.in); for (int i = 0; i < 3; i++) { System.out.println("请输入用户名"); String uName = sc.next(); System.out.println("请输入密码"); String uPwd = sc.next(); if (username.equals(uName) && password.equals(uPwd)) { System.out.println("登录成功"); break; } else { if (i < 2) { System.out.println("用户名或密码不正确,还剩下" + (2 - i) + "次机会"); } else { System.out.println("用户已被锁定"); } } } }
|
键盘录入一个字符串,并在控制台中遍历该字符串
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class StringTopic1 {
public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str = sc.next(); for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); System.out.println(c); } } }
|
键盘录入一个字符串,统计该字符串中大写字符、小写字符、数字字符的出现个数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public static void main(String[] args) { int upperChar = 0; int lowerChar = 0; int digitChar = 0; Scanner sc = new Scanner(System.in); String str = sc.next(); for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if (c >= '0' && c <= '9') { digitChar++; } else if (c >= 'A' && c <= 'Z') { upperChar++; } else if (c >= 'a' && c <= 'z') { lowerChar++; } } System.out.println("大写字符出现了" + upperChar + "次"); System.out.println("小写字符出现了" + lowerChar + "次"); System.out.println("数字字符出现了" + digitChar + "次"); } }
|
定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串返回
调用该方法并在控制台输出结果
例如:
数组为 int[] arr = {1,2,3};
输出结果: [1,2,3]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class StringTopic3 { public static void main(String[] args) { int[] arr = {1, 2, 3}; String result = arrToString(arr); System.out.println(result); }
public static String arrToString(int[] arr) { if (arr == null) { return ""; } if (arr.length == 0) { return ""; } String result = "["; for (int i = 0; i < arr.length; i++) { if (i == arr.length - 1) { result += arr[i]; } else { result += arr[i] + ","; } } return result + "]"; } }
|
定义一个方法 反转一个字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class StringTopic4 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String reverse = reverse(sc.next()); System.out.println(reverse); }
public static String reverse(String str) { String result = "["; for (int i = str.length() - 1; i >= 0; i--) { result += str.charAt(i); } return result + "]"; } }
|
从键盘接入一个用户输入的值
例如: 2135
定义一个方法
将它转换为大写中文字符
如:零佰零拾零万贰仟壹佰叁拾伍元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public class StringTopic5Mirror { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int value = sc.nextInt();
while (true) { if (value > 0 && value < 9999999) { break; } else { System.out.println("输入的值不合理请重新输入"); } } String valueStr = ""; while (true) { int bit = value % 10; valueStr = conversion(bit) + valueStr; value = value / 10; if (value == 0) { break; } }
int count = 7 - valueStr.length(); for (int i = 0; i < count; i++) { valueStr = "零" + valueStr; }
String arr[] = {"佰", "拾", "万", "仟", "佰", "拾", "元"}; String result = ""; for (int i = 0; i < arr.length; i++) { char ch = valueStr.charAt(i); result += ch + arr[i]; } System.out.println(result); }
public static String conversion(int value) { String arr[] = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"}; return arr[value]; } }
|
定义一个手机号码,把中间的号码进行隐藏处理
例如: 定义 13112349841 输出 131****9841
1 2 3 4 5 6 7 8 9
| public class StringTopic6 { public static void main(String[] args) { String phoneNumber = "13112349841"; String start = phoneNumber.substring(0, 3); String end = phoneNumber.substring(7); String authenticNumber = start + "****" + end; System.out.println(authenticNumber); } }
|
根据身份证信息来输出相关出生日期和性别
例如 420111200005011259
输出 出生日期为: 2000年05月01日 性别为男
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class StringTopic7 { public static void main(String[] args) { String id = "420111200005011259"; String year = id.substring(6, 10); String month = id.substring(10, 12); String day = id.substring(12, 14); System.out.println("出生日期为:" + year + "年" + month + "月" + day + "日"); char gender = id.charAt(16); int flag = gender - 48; if (flag % 2 == 0) { System.out.println("性格为女"); } else { System.out.println("性格为男"); } } }
|
屏蔽词替换
1 2 3 4 5 6 7 8 9 10 11
| public class StringTopic8 { public static void main(String[] args) { String shield[] = {"派蒙", "旅行者", "原神"}; String talk = "派蒙不知道哦"; for (int i = 0; i < shield.length; i++) { talk = talk.replace(shield[i], "***"); } System.out.println(talk); } }
|
键盘接入一个字符串,判断它们是否为对称字符串,并在控制台打印是或不是
1 2 3 4 5 6 7 8 9 10 11 12
| public class StringBuilderTopic1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str = sc.next(); StringBuilder builder = new StringBuilder(str); if (builder.reverse().toString().equals(str)) { System.out.println("是"); } else { System.out.println("不是"); } } }
|
定义一个方法,把int数组中的数据安装指定的格式拼接成一个字符串返回
调用该方法,并在控制台输出结果
例如 数组为int[] arr = {1,2,3}
执行方法后的输出结果为: [1,2,3]
1 2 3 4 5 6 7 8 9 10 11
| public class StringBuilderTopic2 { public static void main(String[] args) { int arr[] = {1, 2, 3}; System.out.println(splicing(arr)); }
public static String splicing(int[] arr) { StringBuilder builder = new StringBuilder(); return builder.append(Arrays.toString(arr)).toString(); } }
|
键盘录入一个字符串
要求1:长度为小于等于9
要求2:只能是数字
将内容变成罗马数字
1-Ⅰ、2-Ⅱ、3-Ⅲ、4-Ⅳ、5-Ⅴ、6-Ⅵ、7-Ⅶ、8-Ⅷ、9-Ⅸ
注意点:
罗马数字是没有0的
如果键盘录入的数字包括0,可以变成””(长度为0的字符串)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public class StringTopic1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str; while (true) { System.out.println("输入一个字符串:"); str = sc.next(); boolean flag = verify(str); if (flag) { break; } else { System.out.println("当前字符串不符合规则 请重新输入"); } }
StringJoiner joiner = new StringJoiner(",", "[", "]"); for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); int number = c - 48; joiner.add(conversion(number)); }
System.out.println(joiner.toString());
}
public static String conversion(int number) { String arr[] = {"", "Ⅰ", "Ⅱ", "Ⅲ", "Ⅳ", "Ⅴ", "Ⅵ", "Ⅶ", "Ⅷ", "Ⅸ"}; return arr[number]; }
public static boolean verify(String str) { if (str.length() > 9) { return false; }
for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if (c < '0' || c > '9') { return false; } } return true; }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public class StringTopic1Mirror { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str = ""; System.out.println("输入一个字符串:"); while (true) { str = sc.next(); boolean flag = verify(str); if (flag) { break; } else { System.out.println("输入值有误"); } }
StringJoiner joiner = new StringJoiner(",", "[", "]"); for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); String temp = String.valueOf(c); int value = Integer.parseInt(temp); joiner.add(conversion(value)); } System.out.println(joiner.toString());
}
private static String conversion(int value) { String arr[] = {"", "Ⅰ", "Ⅱ", "Ⅲ", "Ⅳ", "Ⅴ", "Ⅵ", "Ⅶ", "Ⅷ", "Ⅸ"}; return arr[value]; }
private static boolean verify(String str) { if (str.length() > 9) { return false; }
for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); String temp = String.valueOf(c); int value = Integer.parseInt(temp); if (value < 0 || value > 9) { return false; } } return true;
} }
|
给定两个字符串,A和B
A的旋转操作就是将A 最左边的字符移动到最右边
例如,若 A = “abcde” B = “cdeab”, 在移动一次后的结果就是 “bcdea”
如果在若干次调整操作之后 若 A能变成B 则返回 True
如果不能匹配成功则返回false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class StringTopic2 { public static void main(String[] args) { String strA = "abcde"; String strB = "cdeab";
boolean flag = check(strA, strB); if (flag) { System.out.println("匹配成功"); } else { System.out.println("匹配失败"); } }
public static boolean check(String strA, String strB) { for (int i = 0; i < strA.length(); i++) { strA = rotate(strA); if (strA.equals(strB)) { return true; } } return false; }
public static String rotate(String str) { char first = str.charAt(0); String end = str.substring(1); return end + first; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class StringTopic2Mirror { public static void main(String[] args) { String strA = "abcde"; String strB = "cdeab";
boolean flag = check(strA, strB); if (flag) { System.out.println("匹配成功"); } else { System.out.println("匹配失败"); } } public static boolean check(String strA, String strB) { for (int i = 0; i < strA.length(); i++) { strA = rotate(strA); if (strA.equals(strB)) { return true; } } return false; }
public static String rotate(String str) { char first = str.charAt(0); char[] array = str.toCharArray(); for (int i = 1; i < array.length; i++) { array[i - 1] = array[i]; } array[array.length - 1] = first; return new String(array); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 键盘录入一个字符串,打乱字符串里面的内容 ```java public class StringTopic3 { public static void main(String[] args) { String str = "abcdefg"; char[] array = str.toCharArray(); Random r = new Random(); int number = 0; for (int i = 0; i < array.length; i++) { number = r.nextInt(array.length); array[i] = array[number]; } String result = new String(array); System.out.println(result); } }
|
生成验证码
内容:可以是小写字母,也可以是大写字母,还可以是数字
规则
长度为5
内容中是四位数字,一位数字
其中数字只有1位,但是可以出现在任意位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public class StringTopic4 { public static void main(String[] args) { char[] arr = new char[52]; for (int i = 0; i < 26; i++) { arr[i] = (char) ('a' + i); }
int temp = 0; for (int i = 26; i < arr.length; i++) { arr[i] = (char) ('A' + temp); temp++; }
StringBuilder builder = new StringBuilder(); Random r = new Random(); int randomNumber = 0; int i = 0; while (i < 4) { randomNumber = r.nextInt(arr.length); builder.append(arr[randomNumber]); i++; } builder.append(r.nextInt(10));
char temporary; String value = builder.toString(); char[] array = value.toCharArray(); randomNumber = r.nextInt(array.length - 1); temporary = array[randomNumber]; array[randomNumber] = array[array.length - 1]; array[array.length - 1] = temporary; String result = new String(array); System.out.println(result);
} }
|
给定两个字符串形式表示的非负整数num1和num2,返回num1和num2的乘积,它们的乘积表示为字符串的形式
注意:需要使用已有的知识进行完成
不需要考虑乘积过大的后果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public class StringTopic5 { public static void main(String[] args) { String num1 = "123"; String num2 = "654"; int number1 = conversion(num1); int number2 = conversion(num2); System.out.println(number1 * number2); }
public static int conversion(String str) { int result = 0; int arr[] = new int[9]; for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); arr[i] = toInteger(c); } for (int i = 0; i < arr.length; i++) { if (arr[i] == 0) { break; } else { result = result * 10 + arr[i]; } } return result; }
public static int toInteger(char ch) { int[] arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int temp = ch - 48; return arr[temp]; }
}
|
给你一个字符串 s 由若干单词组成,单词前后用一些空格隔开
返回字符串中最后一个单词的长度
单词仅由字母组成、不包含任何空格字符的最大子字符串
示例1
输入 s = “Hello World” 输出:5
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class StringTopic6 { public static void main(String[] args) { String s = "Hello World"; int count = 0; for (int i = s.length() - 1; i > 0; i--) { if (s.charAt(i) == 32) { break; } count++; } System.out.println(count); } }
|