目录
初识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); // falseSystem.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; // 长度小于9for (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;}
}