目录
字符串学习内容
String
概述
java.lang.String类代表字符串,Java程序中的所有字符串文字(例如“abc”)都为此类的对象。
注意点
字符串的内容是不会发生改变的,他的对象在创建后不能被更改
String name = "aaa";
name = "bbb";
这两段代码中,"bbb"是创建了一个新的字符串对象,然后再赋值给变量name,但"aaa"并没有被改变,这个过程中一共产生了两个字符串
创建String对象的两种方式
1、直接赋值:String name = "俊熙";
2、new String(参数):
String s = new String();
String s1 = new String("abc");
char[] ch = {'a','b','c'};//字符数组
String s2 = new String(ch);//根据字符数组的内容再创建一个新的字符串对象
byte[] bytes = {97,98,99,100};//字节数组
String s3 = new String(bytes);//根据字节数组的(ASCII转换后)内容再创建一个新的字符串对象
System.out.println("a" + s + "b");//ab
System.out.println(s1);//abc
System.out.println(s2);//abc
System.out.println(s3);//abcd
直接比较内容的两个方法
· boolean equals方法(要比较的字符串) 完全一样结果才是true,否则为false
· boolean equalsIgnoreCase(要比较的字符串) 忽略大小写的比较
String s1 = new String("abc");
String s2 = "abc";
String s3 = "Abc";
System.out.println(s1 == s2);//false
//直接比较内容
System.out.println(s1.equals(s2));//true
//直接比较内容(忽略大小写)
System.out.println(s1.equalsIgnoreCase(s3));//true
例题
字符串的反转
定义一个方法,实现字符串的反转。键盘录入一个字符串,调用该方法后,在控制台输出结果,例如:键盘录入abc,输出结果cba
思路:运用左右指针的思想对s的字符数组char[] ch进行操作就行,最后返回new String(ch)。
public static void main(String[] args) {
String s1 = "sbcdefg";
char[] ch = s1.toCharArray();//得到s1对应的字符数组
System.out.println(reverse(ch));
}
public static String reverse(char[] ch){
int left = 0,right = ch.length - 1;
while(left < right){
char tmp = ch[left];
ch[left] = ch[right];
ch[right] = tmp;
left++;
right--;
}
return new String(ch);
}
StringBuilder
概述
StringBuilder可以看成是一个容器,创建之后里面的内容是可变的
作用:提高字符串的操作效率
适用场景以及注意事项
适用场景:字符串的反转和拼接
注意:因为StringBuilder是Java已经写好的类,在底层对其做了一些特殊处理,打印对象不是地址值,而是属性值
创建StringBuilder对象
构造方法
常用方法
例题
对称字符串
需求:键盘接受一个字符串,程序判断出该字符串是否是对称字符串,并在控制台打印是或不是
对称字符串:123321、111
非对称字符串:123123
public static void main(String[] args) {
//1、接受一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String s = sc.next();
//2、将字符串反转(链式编程)
String result = new StringBuilder(s).reverse().toString();
//3、字符串比较
boolean flag = result.equals(s);
if (flag) {
System.out.println(s + "是对称字符串");
}else {
System.out.println(s +" 不是对称字符串");
}
}
StringJonier
概述
StringJonier 跟StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的。
作用:提高字符串的操作效率,而且代码编写特别简洁,但是用的人较少
注意事项
StringJonier该方法没有无参构造,使用add方法时只能添加字符串。
创建StringJonier对象
成员方法
例题
public static void main(String[] args) {
StringJoiner sj1 = new StringJoiner("");
sj1.add("aaa").add("123");
System.out.println(sj1.toString());//aaa123
StringJoiner sj2 = new StringJoiner("," , "[" ,"]");
sj2.add("aaa").add("bbb").add("ccc");
System.out.println(sj2);//[aaa,bbb,ccc]
}
知识点
substring(参数)方法
· String substring(int beginIndex, int endIndex) 截取
注意:包头不包尾,包左不包右;只有返回值才会截取的小串
· String substring(int beginIndex) 截取(重载方法,从该位置截取到末尾)
String s = "qeqfw";
System.out.println(s.substring(0,2));//qe
System.out.println(s.substring(2));//qfw
System.out.println(s);//qeqfw
replace(参数)方法
· String replace(旧值,新值) 替换
注意点:只有返回值才是替换之后的结果
String s = "afdaf";
System.out.println(s.replace('a','b'));//bfdbf
System.out.println(s);//afdaf
实际开发中的一些常见案例
用户登录
需求:
已知正确的用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录之后,给出相应的提示
思路:首先定义正确的用户名和密码,然后写出用户登录过程的业务逻辑,最后在加上个for循环即可。
String username = "zhangsan";
String password = "zs181855";
Scanner sc = new Scanner(System.in);
//比较,给三次机会
for (int i = 0; i < 3; i++) {
System.out.println("请输入用户名");
String inputusername = sc.next();
System.out.println("请输入密码");
String inputpassword = sc.next();
if (username.equals(inputusername) && password.equals(inputpassword)) {
System.out.println("用户登录成功");
break;
} else {
if (i==2) System.out.println("账号"+username + "被锁定,请联系相关客服解决");
else System.out.println("用户名或密码错误," + "你还剩" + (2 - i) + "次机会,请重新输入");
}
}
金额转换
用户输入一位整数,将其变成大写。例如:2135-->零佰零拾零万贰仟壹佰叁拾伍元
思路:
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 < 10000000){
break;
}else System.out.println("金额无效");
}
//将数字变成大写中文
String s = "";
while(money != 0){
int n = money % 10;
s = transform(n) + s;
money /= 10;
}
//将零补齐
int end = 7 - s.length();
for (int i = 0; i < end; i++) {
s = '零' + s;
}
//添加单位
char[] ch = {'佰', '拾', '万', '仟', '佰', '拾', '元'};
String result = "";
for(int i = 0; i < ch.length; i++)
result += String.valueOf(s.charAt(i)) + String.valueOf(ch[i]);
System.out.println(result);
}
//定义一个方法,将数字转化为大写
public static char transform(int num){
char[] ch = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};
return ch[num];
}
手机号屏蔽
代码:
String phoneNumber = "12345678901";
String start = phoneNumber.substring(0,3);
String end = phoneNumber.substring(7);
System.out.println(start + "****" + end);
身份证信息查看
根据给定的身份证号,输出一下人物信息
public static void main(String[] args) {
//1、给出一个身份证号,得出对应的信息
String user = "450111197205054878";
//截取第7~14位以及第十七位的数字
String year = user.substring(6,10);
String month = user.substring(10,12);
String day = user.substring(12,14);
char c = user.charAt(16);
//2.打印出生年月日
System.out.println("人物信息为:");
System.out.println("出生年月日:" + year + "年"+ month + "月"+ day + "日");
//3.判断性别
int number = c - 48;//将 '3'->3
if(number % 2 ==0){
System.out.println("性别为:女");
}else {
System.out.println("性别为:男");
}
}
敏感词替换
String talk = "你玩的真好,以后就不要再玩了,TMD,CNM";
String[] arr = {"TMD","CNM", "SB" ,"MLGB"};
//循环得到数组中的每一个敏感词,依此进行替换
for(int i = 0; i < arr.length; i++){
talk = talk.replace(arr[i] , "***");
}
System.out.println(talk);//你玩的真好,以后就不要再玩了,***,***
字符串相关的底层原理
扩展底层原理1:字符串存储的内存原理
内存模型
当使用双引号直接赋值时,系统会检查该字符串在串池中是否存在。不存在:创建新的;存在:复用。
当使用的是new String(参数)时,每new一次就是在堆内存开辟了一个新的小空间,地址空间肯定不会相同
扩展底层原理2:==号比较的到底是什么?
所以,使用双引号直接赋值s1和s2,在s1和s2的内容相等是,比较的结果就是true;除此之外,其他任何情况用==号来比较时,返回的都是false
扩展底层原理3:字符串拼接的底层原理
这里就直接总结了:
· 如果没有变量参与
都是字符串直接相加,编译之后就是拼接之后的结果,会复用串池中的字符串
· 如果有变量参与
JDK8以前:系统底层会自动创建一个StringBuilder对象,然后再调用append方法完成拼接。拼接后,再调用其toString()方法转换为String类型,而toString()方法的底层是直接new了一个字符串对象。
JDK8以后:系统会预估要字符串拼接之后的总大小,把要拼接的内容都放在数组中,此时也是产生了一个新的字符串
都会在内存中创建新的字符串,浪费内存
· 结论
如果很多字符串变量拼接,不要直接+。在底层会创建多个对象,浪费时间,浪费性能。
扩展底层原理4:StringBuilder提高效率原理图
所有要拼接的内容都会往StringBuilder中放,不会创建很多无用的空间,节约内存
扩展底层原理5:StringBuilder源码分析
· 默认创建一个长度为16的字节数组
· 添加的内容长度小于16,直接存
· 添加的内容大于16会扩容(原来的容量*2 + 2)
· 如果扩容之后还不够,以实际长度为准
总结
1、直接赋值字符串,首先会在串池里边找,如果有,则复用;否则,会在串池中创建一个。
2、直接比较内容的两个方法:equals(参数)以及equalsIgnoreCase(参数)。
3、StringBuilder可以看成是一个容器,创建之后里面的内容是可变的,主要适用于字符串的拼接;此外,StringJonier于StringBuilder差不多,但其可以在添加的字符串之间以及头尾“加上一些符号”。
4、介绍了substring(参数)方法以及replace(参数)方法。
5、实际开发中一些小案例以及字符串的底层原理。