java-u1-day19-正则表达式05(String里面的split方法)

Day19 字符串和正则表达式
本章重难点
u String的创建
u 字符串常量
u 字符串比较
u 字符串常用方法
u StringBuffer和StringBuilder
u 正则表达式
1.
String的创建
1.1. String的创建方式
1)String s1=”abc”; //字符串常量池
2)String s2=new String(“abc”); //栈区有一个字符串引用(地址)指向绑定堆区开盘的字符串对象空间
1.2. 以上两种方式创建字符串,有什么区别?
这个问题要说清楚,必须知道字符串和字符串常量。
2.
字符串常量
2.
2.1. 什么是字符串常量池,它放在内存的哪个区?
就是采用双引号引起来的字符串,不是使用new方式构建的就是字符串常量。字符串常量就是放在方法区的常量池中。常量就是不可以改变的量。
2.2. 案例1
画出两种创建字符串的方式在栈、堆、方法区中的内存结构图。
String str; //栈区有一个字符串引用(地址)
String str = “abc”//栈区有一个字符串引用(地址)绑定或者指向一个常量池内容为abc
过程分析:
1) 第1行代码,JVM首先在栈中写入一个引用s1,判断常量池中是否存储abc,如果有,就把abc的首地址赋值给s1,如果没有,就在常量池中新建一个abc,再把首地址赋值给s1.
2) 第2行代码,JVM首先在栈中写入一个引用s2,在堆中通过new String()开辟一块空间,然后把这个空间的首地址赋值给s2的引用。最后在常量池中检查看是否有abc,如果有把abc的首地址赋值给new String()的空间中,如果没有先在常量池中创建,然后再把地址赋值给new String()的空间中。
2.3. 结论
字符串常量直接指向常量池的首地址,字符串变量是指向堆空间,堆空间指向常量池。
2.4. 案例2
案例:分析下来代码在内存中的结构
String str1 = "str";//常量池
String str2 = "ing";//常量池
String str3 = "str" + "ing";//常量池
String str4 = str1 + str2; //在堆中创建新对象
String str5 = "string";////常量池
问题:在编码过程中,如果涉及到多个字符串用+进行拼接,这种方式好不好?如果不是最好的方式,应该采用什么方式进行?(引出StringBuffer和StringBuilder)
不好,他会产生很多的变量在常量池,效率不高,消耗资源。所以,StringBuffer或者是StringBuilder来做拼接,经量少用。
3.
字符串比较相等
3.
3.1. 问题1
需求:有如下代码,分析代码的结果。画出内存结果图
String s1 = "abc";
String s2 = "abc";
System.out.println(s1==s2);//true
3.2. 问题2
需求:有如下代码,分析代码的结果。画出内存结果图
String s1 =String( "abc");
String s2 =String( "abc");
System.out.println(s1==s2);//false
3.3. 字符串比较的结论
1) ==在比较字符串对象的时候用来比较什么?
比较地址,只适用于字符串常量池
2) 如果要比较内容是否相等,采用什么方式?
equals():内容是否相等,通过源代码分析,首先比较的是地址是否相等,如果相等就是true,如果地址不相等,就一个字符一个字符对应进行比较。看是否相等,它是重写了Object对象的equals()方法,Object中的equals()比较的是地址。
4.
字符串对象的方法
4.
4.1. String的相关方法
l boolean equals(Object obj):比较字符串的内容是否相同
l boolean equalsIgnoreCase(String str): 比较字符串的内容是否相同,忽略大小写
l boolean startsWith(String str): 判断字符串对象是否以指定的str开头
l boolean endsWith(String str): 判断字符串对象是否以指定的str结尾
4.2. 案例3
需求:编写一个测试类,测试这些方法,加深印象
public class StringTest {
public static void main(String[] args) {
//1、比较字符串的内容是否相同
String s1="hello";//常量池
String s2=new String("hello");//字符串堆内容
System.out.println(s1.equals(s2));
//2、比较字符串的内容是否相同,忽略大小写
String s3="HeLLo";
System.out.println(s1.equalsIgnoreCase(s3));
//3、判断字符串对象是否以指定的str开头
String filename="abc_f.txt";
System.out.println(filename.startsWith("1abc"));
//4、判断字符串对象是否以指定的str结尾
System.out.println(filename.endsWith(".tx1t"));
}
}
l int length():获取字符串的长度,其实也就是字符个数
l char charAt(int index):获取指定索引处的字符
l int indexOf(String str):获取str在字符串对象中第一次出现的索引
l String substring(int start):从start开始截取字符串
l String substring(int start,int end):从start开始,到end结束截取字符串。包括start,不包括end
l char[] toCharArray():把字符串转换为字符数组
l String toLowerCase():把字符串转换为小写字符串
l String toUpperCase():把字符串转换为大写字符串
4.3. 案例4
需求:编写一个测试类,测试这些方法,加深学员印象
public class StringTest1 {
public static void main(String[] args) {
String s1="abcdef";
//length():获取字符串的长度,其实也就是字符个数
System.out.println(s1.length());
//charAt(int index):获取指定索引处的字符
char c=s1.charAt(1);
System.out.println(c);
//int indexOf(String str):获取str在字符串对象中第一次出现的索引
int index=s1.indexOf("deccc");
System.out.println(index);
//String substring(int start):从start开始截取字符串
String ss=s1.substring(3);//def
System.out.println(ss);
String s2=s1.substring(1,3);
System.out.println(s2);//bc
//char[] toCharArray():把字符串转换为字符数组
char[] chars = s1.toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
//String toLowerCase():把字符串转换为小写字符串
String v_s1="AvcD45E";
System.out.println(v_s1.toLowerCase());
// String toUpperCase():把字符串转换为大写字符串
System.out.println(v_s1.toUpperCase());
}
}
4.4. 案例5
需求:获取指定字符串中,大写字母、小写字母、数字的个数。
大写字母:一个字符(char)ch ch>=’A’ && ch<=’Z’
小写字母:一个字符(char)ch ch>=’a’ && ch<=’z’
数字:一个字符(char)ch ch>=’0’ && ch<=’9’
1)思路分析和伪代码
a、字符如何比较大小,在字母表中的先后顺序;字符本身在计算机中的内存中用数字来描述的。
b、可以将字符串转成字符数组,然后循环比较它的范围,如果在'a'-'z',这就是小写字母;如果在'A'-'Z'这是大写字母,在'0'-'9'返回就是数字。外面用几个计数器来计数就可以了
2)编码实现
public class StringTest2 {
public static void main(String[] args) {
String s="12CRcyuAdwDF09Km";
//1、将字符串转成字符数组
char[] chars = s.toCharArray();
//2、定义3个计数器
int m=0;//计数小写字母
int n=0;//计数大写字母
int k=0;//计数数字
for (char c:chars){
if(c>='a'&&c<='z'){
m++;
}
if(c>='A'&&c<='Z'){
n++;
}
if(c>='0'&&c<='9'){
k++;
}
}
System.out.println("小写字母:"+m+" 大写字母:"+n+" 数字:"+k);
}
}
5.
StringBuffer和StringBuilder
问题:String作为字符串使用已经可以满足我们的需要,为什么还会出现现在的这个两个对象?
因为当多个字符串进行连接操作,也就是通过+方法进行拼接字符串的时候,会在常量池中有有过多的临时对象,这样内存中的垃圾很多,我们要解决该问题。所以出现了字符串缓存对象。
5.
5.1. 相关知识要点
1)String 是不可变的,StringBuffer、StringBuilder 是可变的;
2)String 、StringBuffer 是线程安全的,StringBuilder 不是线程安全的。
3)StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类
5.2. StringBuilder的相关方法
1)append(),追加到字符串的末位
2)insert() 插入到指定位置
3)delete() 删除字符串
4)reverse() 反转
/*
要点:
1、StringBuilder对象默认是将字符串放到它的字符数组char[]中的,它的初始的长度是16
2、该对象是可变的,追加的时候不好在常量池放临时对象,而是放在该对象的字符数组中。
3、当追加的时候,会计数追加字符串的长度,然后将它+16,作为现在char[]数组的长度
4、该对象不是字符串,要获得该对象的字符串表示,可以用toString()方法获得字符串
*/
public class StringBuilderTest {
public static void main(String[] args) {
StringBuilder sb=new StringBuilder("abc");
//1)append(),追加到字符串的末位
sb.append("123").append("456").append("yyy");
System.out.println(sb.toString());
//2)insert() 插入到指定位置,第1个参数是偏移量,也就是偏移几个字母追加。第2个参数是追加的数据
sb.insert(1,"zz");
System.out.println(sb.toString());
//3)delete() 删除字符串,第1个参数是开始索引,第2个参数是结束索引
sb.delete(1,3);
System.out.println(sb.toString());
//4)reverse() 反转
sb.reverse();
System.out.println(sb.toString());
}
}
6.
正则表达式
6.
6.1. 为什么要学习正则表达式?
因为对于某些字符串要进行格式的匹配,这样的需求用传统拆分字符串然后写业务逻辑的方式去处理,业务 逻辑的写法非常复杂。正则表达式可以很方便的做到。而且字符串有专门支持正则表达式进行匹配的方法。我们在使用的时候只要写正则表达式,然后调用字符串的匹配方法就可以完成逻辑的验证操作。
Tip:学习的目的:解决字符串的个性化判断问题,如果没有正则表达式,ifelse就会无穷无尽
6.2. 什么是正则表达式?
又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
6.3. 相关规则
A、规定字符(每一个)出现的内容
0-9之间的数字:\d [0-9]
字母和数字: \w [a-zA-Z0-9]
取反:^ 比如描述非数字[^0-9]
出现点号 \\.
B、规定字符串或者字符出现的频率(次数)
? 0次或者1次
+ 1次或者1次以上
* 表示0次或者0次以上
{n} 字符串或者字符出现n次
{n,m} 最少出现n次,最多出现m次
{n,} 出现n次以上包括n次,比如密码长度超过6位:{6,}
6.4. String字符串的正则表达式的方法
1) matches(正则表达式),返回值是boolean
2) replaceAll(字符串,正则),用正则替换字符串中的子串
6.5. 案例6
需求:判断一个字符串是否是手机字符串"13533839778",手机号的规则:
0.手机号的长度必须是11位:{11}
1.手机号的第一位必须是1
2.手机号的第二位:3或4或5或7或8
3.手机号的剩余九位的每一位都必须是数字
public class RegTest1 {
public static void main(String[] args) {
//1、定义字符串存储手机号
String phone="13533839778";
//2、定义一个正则表达式
String reg="1[34578]\\d{9}";
//3、利用字符串函数进行匹配
boolean result = phone.matches(reg);
System.out.println(result);
}
}
6.6. 案例7
案例:将字符串“abcpof67kkk12kkk5sss”中的数字变成汉字“我们”
1)思路分析
2)编码实现
public class RegTest2 {
public static void main(String[] args) {
//1、定义一个等待检查的字符串
String s = "abcpof67kkk12kkk5sss";
//2、定义一个正则表达式
String reg="\\d";
//3、用字符串的替换方法
String s1 = s.replaceAll(reg, "我们");
//4、输出结果
System.out.println(s1);
}
}
6.7. 案例8
需求:注册的时候要求用户输入邮箱,规则是:
1)字母开头,中间可以是字母数字下划线或$.
2)接着是@
3)是字母长度不超过10位
4).和字母长度不超过3位
5)后面还可以接一个.字母,长度不能超过3位
编码验证改邮箱yy_y$_222y@sina.com.cn是否合法
public class RegTest3 {
public static void main(String[] args) {
String email="yy_y$_222y@sina.com.cn";
String reg="[a-zA-Z][\\w_$]{5,}@[a-zA-Z]{1,10}(\\.[a-zA-Z]{2,3}){1,2}";
boolean result = email.matches(reg);
System.out.println(result);
}
}