目录
初识String
StringBuilder
StringJoiner
字符串原理
综合练习
初识String
java.lang.String 类代表字符串,Java程序中的所有字符串文字(例如“abc”)都为此类的对象,例:
String name = "张三"
当使用双引号直接赋值时,系统会检查该字符串在串池中是否存在,如果不存在就创建,如果存在则复用原地址。
注意:字符串的内容是不会发生改变的,它的对象在创建后不能被更改。创建对象有两种方式,一种就是上面的直接赋值方式,另一种就是通过下面 new 的方式:
构造方法 | 说明 |
---|---|
public String() | 创建空白字符串,不含任何内容 |
public String(String original) | 根据传入的字符串,创建字符串对象 |
public String(char[] chs) | 根据字符数组,创建字符串对象 |
public String(byte[] chs) | 根据字节数组,创建字符串对象 |
字符串的创建:以下是通过new关键字创建字符串的相关方法:
public class StringDemo {
public static void main(String[] args) {
// 使用new的方式来获取一个字符串对象
// 空参构造:可以获取一个空白的字符串对象
String s1 = new String();
System.out.println("@"+s1+"!"); // ""
// 传递一个字符串,根据传递的字符串内容再创建一个新的字符串对象
String s2 = new String("abc");
System.out.println(s2);
// 传递一个字符数组,根据字符数组的内容再创建一个新的字符串对象
char[] chs = { 'a', 'b', 'c', 'd' };
String s4 = new String(chs);
System.out.println(s4);
// 传递一个字节数组,根据字节数组的内容再创建一个新的字符串对象
byte[] bytes = { 97, 98, 99, 100 };
String s5 = new String(bytes);
System.out.println(s5); // 查找scall表中的数据
}
}
字符串的比较:关于字符串的比较有以下两个注意点:
public class StringDemo {
public static void main(String[] args) {
// 基本数据类型比较的是数据值
int a = 10;
int b = 10;
System.out.println(a == b); // true
// 引用数据类型比较的是地址值
String s1 = new String("abc");
String s2 = new String("abc");
String s3 = "abc";
System.out.println(s1 == s2); // false
System.out.println(s1 == s3); // false
}
}
关于字符串的比较这里也可以采用相应的API进行使用:
public class StringDemo {
public static void main(String[] args) {
// 创建两个字符串对象
String s1 = new String("abc");
String s2 = "abc";
String s3 = "Abc";
// 比较字符串对象中的内容是否相等
boolean result1 = s1.equals(s2);
System.out.println(result1); // true
// 比较字符串中的内容是否相等,忽略大小写
boolean result2 = s1.equalsIgnoreCase(s3);
System.out.println(result2); // true
}
}
这里我们通过如下的登录账号密码的案例加深对上面的理解学习:
public class StringDemo {
public static void main(String[] args) {
// 定义两个变量记录正确用户名和密码
String rightUsername = "zhangsan";
String rightPassword = "123456";
// 键盘录入用户名和密码
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
System.out.println("请输入用户名:");
String username = sc.next();
System.out.println("请输入密码:");
String password = sc.next();
// 比较
if (username.equals(rightUsername) && password.equals(rightPassword)) {
System.out.println("用户登录成功!");
break;
} else {
if (i == 2) {
System.out.println("账号"+ username+"被锁定,请联系管理员");
} else {
System.out.println("用户登录失败,用户名或密码错误! 您还剩下"+(2 - i)+"次机会");
}
}
}
}
}
效果如下所示:
字符串的遍历:关于字符串的遍历可以通过如下的方式进行:
public class StringDemo {
public static void main(String[] args) {
// 键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
// 进行遍历
for (int i = 0; i < str.length(); i++) {
// i 依次表示字符串的每一个索引
char c = str.charAt(i);
System.out.println(c);
}
}
}
字符串统计:统计字符串中大小写字母字符数字字符出现的次数:
public class StringDemo {
public static void main(String[] args) {
// 键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
// 定义三个计数器
int bigCount = 0;
int smallCount = 0;
int numberCount = 0;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c >= 'a' && c <= 'z') { // char类型的变量参与计算的时候自动类型提升为int,查询ascii码表
smallCount++;
} else if (c >= 'A' && c <= 'Z') {
bigCount++;
} else if(c >= '0' && c <= '9') {
numberCount++;
}
}
// 输出打印
System.out.println("小写字母有:" + smallCount + "个");
System.out.println("大写字母有:" + bigCount + "个");
System.out.println("数字字母有:" + numberCount + "个");
}
}
字符串的拼接:可以通过如下案例操作实现字符串的拼接:
public class StringDemo {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
String str = arrToString(arr);
System.out.println(str);
}
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 = result + arr[i];
} else {
result = result + arr[i] + ", ";
}
}
// 此时拼接右括号
result = result + "]";
return result;
}
}
字符串的反转:关于字符串的反转,我们可以定义如下函数进行操作:
public class StringDemo {
public static void main(String[] args) {
String result = reverser("abc");
System.out.println(result); // cba
}
public static String reverser(String str) {
String result = "";
for (int i = str.length() - 1; i >= 0; i--) {
char c = str.charAt(i);
result = result + c;
}
return result;
}
}
下面是一个字符串相关转换拼接的案例:
import java.util.Scanner;
public class StringDemo {
public static void main(String[] args) {
// 键盘录入一个金额
Scanner sc = new Scanner(System.in);
int money;
while (true) {
System.out.println("请输入一个金额");
money = sc.nextInt();
if (money >= 0 && money <= 9999999) {
break;
} else {
System.out.println("金额无效");
}
}
// 定义一个变量用来表示钱的大写
String moneyStr = "";
// 得到money中的每一位数字
while (true) {
// 从右往左获取数据,因为右侧是数据的个位
int ge = money % 10;
String capitalNUmber = getCapitalNumber(ge);
// 把转换之后的大写拼接到moneyStr当中
moneyStr = capitalNUmber + moneyStr;
// 去掉刚刚获取到的数据
money = money / 10;
// 如果数字上的每一位都获取到了,那么money记录的就是0,此时循环结束
if (money == 0) break;
}
// 在前面补0,补7位
int count = 7 - moneyStr.length();
for (int i = 0; i < count; i++) {
moneyStr = "零" + moneyStr;
}
// 插入单位
String[] arr = { "佰", "拾", "万","仟", "佰", "拾", "元" };
// 遍历moneyStr,依次把插入单位插入到对应的moneyStr位置上
String result = "";
for (int i = 0; i < moneyStr.length(); i++) {
char c = moneyStr.charAt(i);
result = result + c + arr[i];
}
// 打印最终结果
System.out.println(result);
}
// 定义一个方法把数字变成大写的中文
public static String getCapitalNumber(int number) {
// 定义数组,让数字跟大写的中文产生一个对应关系
String[] arr = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌" };
// 返回结果
return arr[number];
}
}
StringBuilder
StringBuilder可以看成是一个容器,创建之后里面的内容是可变的。作用是提高字符串的操作效率。因为StringBuilder是Java已经写好的类,java在底层对他做了一些特殊处理,打印对象不是地址值而是属性值。
以下是StringBuilder的构造方法:
方法名 | 说明 |
---|---|
public StringBuilder() | 创建一个空白可变字符串对象,不含有任何内容 |
public StringBuilder(String str) | 根据字符串的内容,来创建可变字符串对象 |
以下是StringBuilder的成员方法:
通过如下的代码案例进行理解:
public class StringDemo {
public static void main(String[] args) {
// 创建对象
StringBuilder str = new StringBuilder("abc");
// 添加元素
str.append(1);
str.append(1.2);
str.append(true);
System.out.println(str);
str.reverse(); // 反转
System.out.println(str);
// 使用完 StringBuilder 工具之后,再把StringBuilder变回字符串
String Str = str.toString();
System.out.println(Str);
}
}
StringJoiner
StringJoiner跟StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的。其作用是提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用。在JDK8开始出现:
以下是StringJoiner的构造方法:
方法名 | 说明 |
---|---|
public StringJoiner (间隔符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号 |
public StringJoiner(间隔符号,开始符号,结束符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号、开始符号、结束符号 |
以下是StringJoiner的成员方法:
方法名 | 说明 |
---|---|
public StringJoiner add (添加的内容) | 添加数据,并返回对象本身 |
public int length() | 返回长度(字符出现的个数) |
public String toString() | 返回一个字符串 (该字符串就是拼接之后的结果) |
通过如下的代码案例进行理解:
import java.util.StringJoiner;
public class StringDemo {
public static void main(String[] args) {
// 创建一个对象,并指定中间的间隔符号
StringJoiner sj = new StringJoiner("---", "[", "]");
// 添加元素
sj.add("aaa").add("bbb").add("ccc");
// 打印结果
System.out.println(sj);
}
}
字符串原理
关于字符串的原理我们需要掌握以下几个概念:
字符串存储的内存原理
直接赋值会复用字符串常量池中的,而new出来不会复用,而是开辟一个新的空间
==号比较的到底是什么?
基本数据类型比较数据值,而引用数据类型比较地址值
字符串拼接的底层原理
拼接的时候没有变量,都是字符串;触发字符串的优化机制,在编译的时候就已经是最终的结果了。
在拼接的时候有变量,JDK8以前底层会使用StringBuilder,每一行拼接的代码,都会在内存中创建新的字符串,浪费内存。
StringBuilder提高效率原理图
字符串拼接的时候,如果有变量:
JDK8以前:系统底层会自动创建一个StringBuilder对象,然后再调用其append方法完成拼接。拼接后,再调用其toString方法转换为String类型,而toString方法的底层是直接new了一个字符串对象。
JDK8版本:系统会预估要字符串拼接之后的总大小,把要拼接的内容都放在数组中,此时也是产生一个新的字符串。
综合练习
转换罗马数字:题目要求如下:
键盘录入一个字符串
要求1:长度为小于等于9
要求2:只能是数字将内容变成罗马数字下面是阿拉伯数字跟罗马数字的对比关系:
I-1、II-2、III-3、IV-4、V-5、VI-6、VIl-7、Vl-8、Ix-9
注意点:
罗马数字里面是没有0的,如果键盘录入的数字包含0,可以变成”"(长度为0的字符串)
import java.util.Scanner;
public class StringDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str;
while (true) {
// 键盘录入一个字符串
System.out.println("请输入一个字符串:");
str = sc.next();
// 校验字符串是否满足规则
boolean flag = checkStr(str);
if (flag) {
break;
} else {
System.out.println("当前的字符串不符合规则,请重新输入!");
continue;
}
}
// 将内容变成罗马数字
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
int number = c - 48;
String result = changeLuoMa(number);
sb.append(result + ", ");
}
System.out.println(sb);
}
public static String changeLuoMa(int number) {
// 定义一个数组,让索引跟罗马数字产生对应关系
String[] arr = { "", "I", "II", "III", "IV", "V", "VI", "VII", "VI", "IX" };
return arr[number];
}
public static boolean checkStr(String str) {
if (str.length() > 9) return false; // 长度小于9
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c < '0' || c > '9') return false;
}
return true;
}
}
调整字符串:题目要求如下:
给定两个字符串,A和 B。
A 的旋转操作就是将 A最左边的字符移动到最右边。
例如,若A='abcde',在移动一次之后结果就是'bcdea′。
如果在若干次调整操作之后,A能变成B,那么返回True,如果不能匹配成功,则返回false。
public class StringDemo {
public static void main(String[] args) {
// 定义两个字符串
String strA = "abcde";
String strB = "cdeab";
// 调用方法进行比较
boolean result = check(strA, strB);
// 输出结果
System.out.println(result);
}
public static boolean check(String strA, String strB) {
for (int i = 0; i < strB.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;
}
}