第二十四章 字符串操作类
提纲
- 24.1 String类
- 24.1.1 什么是String
- 24.1.2 声明一个字符串
- 24.1.3 创建字符串
- 24.2 连接字符串
- 24.2.1 连接多个字符串
- 24.2.2 连接其他数据类型
- 24.3 获取字符串信息
- 24.3.1 获取字符串的长度
- 24.3.2 字符串查找
- 24.3.3 获取指定索引位置的字符
- 24.4 字符串操作
- 24.4.1 获取子字符串
- 24.4.2 去除字符串首尾空格
- 24.4.3 字符串替换
- 24.4.4 判断字符串的开始与结尾
- 24.4.5 判断字符串是否相等
- 24.4.6 字母大小写转换
- 24.4.7 字符串分割
- 24.4.8 将字符串转化字节(getBytes())或字符(toCharArray())数组
- 24.5 格式化字符串
- 24.5.1 日期和时间字符串格式化
- 24.5.1.1 日期格式化
- 24.5.1.2 时间格式化
- 24.5.1.3 常见的日期时间组合
- 24.5.1.4 常规类型格式化
- 24.5.1 日期和时间字符串格式化
- 24.6 正则表达式
- 24.6.1 什么是正则表达式
- 24.6.2 为什么使用正则表达式举例
- 24.6.3 各个字符的含义
- 24.6.4 使用举例
- 24.6.5 最全的常用正则表达式大全
- 24.7 字符串生成器
- 24.7.1 StringBuilder的作用
- 24.7.2 StringBuilder中的方法
- 24.7.3 StringBuffer类
- 24.8 作业
24.1 String类
-
24.1.1 什么是String:由于char类型只能表示单个字符,所以要表示多个字符连接成的一个字符串必须通过java.lang中的String类来处理。
-
24.1.2 声明一个字符串:在Java语言中字符串必须包含在双引号(“”)之内。例如:“10.3”,“ADWQ21”,“你好”。这些都是字符串常量,字符串常量是系统能够显示任何文字信息,甚至是单个字符。不过要注意的是:在Java中用(“”)包围的都是字符串,不能作为其他数据使用,比如"1+2"直接输出就是1+2,不会是3。也就是说双引号中是什么样子,使用的时候就是什么样子。
//声明字符串语法: String str;//其中String:代表指定该变量为字符串类型,str:任意有效的变量名称。
注意:声明字符串如果要使用(比如打印,调用String中的方法)就必须要赋初始值,否则编译器会报出错误。
-
24.1.3 创建字符串:String可以直接创建字符串对象。常用构造方法如下:
-
String(String original):初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
String s = new String("hello");
-
String(char[] value):用一个字符数组创建String对象。
char[] a = {'h','e','l','l','o'}; String s = new String(a); //相当于 String s = new String("hello");
-
String(char[] value, int offset, int length):提取字符数组中的一部分创建字符串对象。参数offset表示开始截取字符串的位置,length表示截取字符串的长度。截取位置下标从0开始。
char[] a = {'h','e','l','l','o'}; String s = new String(a,2,2); //相当于 String s = new String("ll");
-
除了通过以上几种使用String的构造方法来创建字符串变量外,还可通过字符串常量的引用赋值给一个字符串变量。
String str1,str2; str1 = "我是一个学生"; str2 = "我是一个学生";
注意:这两个不同的引用指向同一个对象。
-
24.2 连接字符串
对于已声明的字符串,可以对其进行相应的操作。连接字符串就是字符串操作中较简单的一种。
可以多个字符串进行连接。也可以与其他数据类型进行连接。
-
24.2.1 连接多个字符串:使用“+”运算符可实现连接多个字符串功能。可以连接多个“+”运算符连接并产生一个String对象。
public static void main(String[] args) { String s1 = new String("hello"); String s2 = new String("world!"); String s3 = new String("i'm Java!"); String s = s1+" "+s2+" "+s3; System.out.println("新的字符串:"+s); } //执行结果 新的字符串:hello world! i'm Java! Java中一句相连的字符串不能分开在两行写,而是必须用“+”连接成两个字符串。比如: //如果一个字符串太长,便于阅读可以写两行,但是不能这样写 String s4 = "11111111111111111111111111111111111111111 22222222222222222222222222222222222222222222"; //必须分隔成两个字符串并用“+”号连接 String s4 = "11111111111111111111111111111111111111111"+ "22222222222222222222222222222222222222222222";
-
24.2.2 连接其他数据类型:字符串也可同其他基本数据类型进行连接。如果字符串同这些数据类型数据进行连接,会将这些数据直接转换成字符串。
-
举例:
int booktime = 4; float practice = 2.5f; System.out.println("我每天花费:"+booktime+"小时看书,"+practice+"小时上机练习。"); System.out.println("我每天花费:"+booktime+"小时看书," +practice+"小时上机练习。总共花了:"+(booktime+practice)+"小时。"); System.out.println("我每天花费:"+booktime+"小时看书," +practice+"小时上机练习。总共花了:"+booktime+practice+"小时。"); //执行结果 我每天花费:4小时看书,2.5小时上机练习。 我每天花费:4小时看书,2.5小时上机练习。总共花了:6.5小时。 我每天花费:4小时看书,2.5小时上机练习。总共花了:42.5小时。
-
结论:
- 当其他类型与字符串连接时会自动调用toString方法,将其转换成字符串形式,然后参与连接。
- 只要是“+”运算符左右其中一个操作数是字符串,编译器就会把另一个操作数转换成字符串形式。
- 如果想要两个数字相加的结果应该使用括号将它们括起来。因为运算符中圆括号的优先级最高,所以会先执行圆括号中的内容再与其他字符串相连接。
-
24.3 获取字符串信息
字符串作为对象,可以通过相应方法获取字符串的有效信息,如获取某字符串的长度、某个索引位置的字符串。
-
24.3.1 获取字符串的长度:length()方法可获取声明字符串对象的长度。
String str = "We are students!"; int size = str.length(); System.out.println("字符串的长度是:"+size); //执行结果 字符串的长度是:16
注意:字符串中一个空格算做一个长度。
-
24.3.2 字符串查找:String提供了两种查找字符串的方法,即indexOf()与lastIndexOf()方法。
-
indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引。此方法会从字符串的开始位置开始搜索str的位置,如果没有检索到字符串str,该方法返回-1。
String str = "We are students!"; int index = str.indexOf("a"); System.out.println("字符串a的索引是:"+index); //执行结果 字符串a的索引是:3
结论:在计算机中String对象是用数组表示的,所以字符串的下标是从0~length()-1。
-
lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引。此方法会从当前字符串的开始位置检索字符串,并将最后一次出现str的索引位置返回。可以理解为从字符串的末尾开始检索,然后将第一次出现str字符串的索引位置(注意:索引仍旧要从左往右数)返回。如果没有检索到字符串str,则返回-1。
String str = "We are students!"; int index = str.indexOf("s"); int lastIndex = str.lastIndexOf("s"); int spaceIndex = str.indexOf(""); int spaceLastIndex = str.lastIndexOf(""); //传入一个没有的字符串,返回-1 System.out.println(str.indexOf("x")); System.out.println("字符串s从第一次出现的索引是:"+index); System.out.println("字符串s从最后一次出现的索引是:"+lastIndex); System.out.println("当传入空的字符串第一次所出现的索引是:"+spaceIndex); System.out.println("当传入空的字符串最后一次出现的索引是:"+spaceLastIndex); //执行结果 字符串s从第一次出现的索引是:7 字符串s从最后一次出现的索引是:14 当传入空的字符串第一次所出现的索引是:0 当传入空的字符串最后一次出现的索引是:16
结论:1.当传入空的字符串时,indexOf()方法返回的是0,即字符串的开头是空的。同理,结尾也是空的。
-
indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
String str = "hello world!"; int index1 = str.indexOf("o", 0); int index2 = str.indexOf("o", 5); System.out.println("从索引0开始检索字符o第一次出现的索引为:"+index1); System.out.println("从索引5开始检索字符o第一次出现的索引为:"+index2); //执行结果 从索引0开始检索字符o第一次出现的索引为:4 从索引5开始检索字符o第一次出现的索引为:7
-
lastIndexOf(int ch, int fromIndex):返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索。
-
-
24.3.3 获取指定索引位置的字符:使用charAt()方法
String str = "hello world!"; char ch = str.charAt(6); System.out.println("第6个位置的字符是:"+ch); //执行结果 第6个位置的字符是:w
24.4 字符串操作
-
24.4.1 获取子字符串
-
substring(int beginIndex):返回一个新的字符串,它是此字符串的一个子字符串。该方法是从指定的索引开始截取到该字符串结尾的字串。
-
substring(int beginIndex, int endIndex):返回一个新字符串,它是此字符串的一个子字符串。该方法是从指定开始索引和指定结束索引来截取字符串。
String str = "hello world!"; String newStr1 = str.substring(6); String newStr2 = str.substring(1, 4); System.out.println("从指定索引截取到该字符串结尾:"+newStr1); System.out.println("从指定开始索引和指定的结束索引截取该字符串:"+newStr2); //执行结果 从指定索引截取到该字符串结尾:world! 从指定开始索引和指定的结束索引截取该字符串:ell
-
-
24.4.2 去除字符串首尾空格:trim()方法,返回字符串的副本,忽略前导空白和尾部空白。
String str = " hello world! "; String newTrim = str.trim(); System.out.println("原来的字符串:"+str+"-"); System.out.println("去除首尾空格后的字符串:"+newTrim); //执行结果 原来的字符串: hello world! - 去除首尾空格后的字符串:hello world!
-
24.4.3 字符串替换:replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。如果要替换的字符没有出现在字符串中,则返回原字符串。replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
String str = "hello world!"; String newStr = str.replace("l", "A"); System.out.println("替换前的字符串:"+str); System.out.println("替换后的字符串:"+newStr); String str3 = "We are students!"; String newStrRe2 = str3.replace("students", "teachers"); System.out.println("替换后的字符串:"+newStrRe2); //执行结果 替换前的字符串:hello world! 替换后的字符串:heAAo worAd!
-
24.4.4 判断字符串的开始与结尾
-
startsWith(String prefix):测试此字符串是否以指定的前缀开始。
-
endsWith(String suffix):测试此字符串是否以指定的后缀结束。
String str = "hello world!"; boolean bstart = str.startsWith("he"); boolean bend = str.endsWith("ld"); System.out.println("字符串str是以he开始吗:"+bstart); System.out.println("字符串str是以ld结尾吗:"+bend); //执行结果 字符串str是以h开始吗:true 字符串str是以d结尾吗:false
-
-
24.4.5 判断字符串是否相等
- equals(Object anObject):判断两个对象的内容是否相等
- equalsIgnoreCase(String anotherString):将此 String 与另一个 String 内容进行比较,不考虑大小写。
-
24.4.6 字母大小写转换
-
toLowerCase(): 使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
-
toUpperCase():使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
String str1 = new String("abc DEF"); System.out.println("toLowerCase():"+str1.toLowerCase()); System.out.println("toUpperCase():"+str1.toUpperCase());
-
-
24.4.7 字符串分割
-
split(String regex):根据给定正则表达式的匹配拆分此字符串。即按照指定的规则分割字符串。
-
split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串。limit:limit 参数控制模式应用的次数,因此影响所得数组的长度。如果该限制 n 大于 0,则模式将被最多应用 n - 1 次,数组的长度将不会大于 n,而且数组的最后一项将包含所有超出最后匹配的定界符的输入。如果 n 为非正,那么模式将被应用尽可能多的次数,而且数组可以是任何长度。如果 n 为 0,那么模式将被应用尽可能多的次数,数组可以是任何长度,并且结尾空字符串将被丢弃。
-
举例:
-
例1:
例如,字符串 "boo:and:foo" 使用这些参数可生成以下结果: Regex Limit 结果 : 2 { "boo", "and:foo" } : 5 { "boo", "and", "foo" } : -2 { "boo", "and", "foo" } o 5 { "b", "", ":and:f", "", "" } o -2 { "b", "", ":and:f", "", "" } o 0 { "b", "", ":and:f" }
-
例2:
String str = "192.168.0.1"; //按照.进行分割,使用转义字符“\\.” String[] strArr1 = str.split("\\."); //按照.进行(2-1)次分割,使用转义字符“\\.” String[] strArr2 = str.split("\\.", 2); //输出原字符串的值 System.out.println("原字符串的值为:"+str); System.out.print("全部分割的结果:"); for (int i = 0; i < strArr1.length; i++) { System.out.print(strArr1[i]+" "); } System.out.println(); System.out.print("分割(2-1)次的结果:"); for (int i = 0; i < strArr2.length; i++) { System.out.print(strArr2[i]+" "); } //执行结果 原字符串的值为:192.168.0.1 全部分割的结果:192 168 0 1 分割(2-1)次的结果:192 168.0.1
-
-
-
24.4.8 将字符串转化字节(getBytes())或字符(toCharArray())数组
//将字符串转化成char型数组 char[] chs = str3.toCharArray();//char[] chs = {'W','e',' '.....}; for (int i = 0; i < chs.length; i++) { System.out.println(chs[i]); } //将字符串转化成byte型数组 byte[] bys = str3.getBytes(); for (int i = 0; i < bys.length; i++) { System.out.println(bys[i]); }
24.5 格式化字符串
格式化字符串方法:format(String format, Object... args),使用指定的格式字符串和参数返回一个格式化字符串。
其中:
format - 字符串的转换格式
args - 格式字符串中由格式说明符引用的参数。如果还有格式说明符以外的参数,
则忽略这些额外的参数。参数的数目是可变的,可以为 0。
- 24.5.1 日期和时间字符串格式化
- 24.5.1.1 日期格式化
-
常用的日期格式化转换符
转换符 说明 示例 %te 一个月中的某一天(1~31) 2 %tb 指定语言环境的月份简称 Feb(英文)、二月(中文) %tB 月份全称 February(英文)、二月(中文) %tA 星期几的全称 Monday(英文)、星期一(中文) %ta 星期几的简称 Mon(英文)、星期一(中文) %tc 包括全部日期和时间信息 星期二 三月 25 13:37:22 CST 2008 %tY 4位年份 2008 %tj 一年中的第几天 085 %tm 月份 03 %td 一个月中的第几天 02 %ty 2位年份 08
-
举例:
public static void main(String[] args) { Date date = new Date(); System.out.println("格式化之前的时间显示:"+date); System.out.println("今年是:"+String.format("%tY", date)+"年"); System.out.println("现在是:"+String.format("%tB", date)); System.out.println("今天是:"+String.format("%td", date)+"日"); System.out.println(String.format("%tA", date)); System.out.println("今天是一年中的第"+String.format("%tj", date)+"天"); } //执行结果 格式化之前的时间显示:Wed Oct 25 15:21:52 CST 2017 今年是:2017年 现在是:十月 今天是:25日 星期三 今天是一年中的第298天
-
- 24.5.1.2 时间格式化
-
常用的时间格式化转换符
转换符 说明 示例 %tH 2位数字的24小时制的小时(00~23) 14 %tI 12小时制小时(01~12) 05 %tk 24小时制小时(0~23) 5 %tl 12小时制小时(1~12) 10 %tM 分钟(00~59) 05 %tS 秒数(00~60) 12 %tL 3为数字的毫秒数(000~999) 920 %tN 9位数字的微秒数(9个0~9个9) 062000000 %tp 指定语言环境上午或下午的标记 下午(中文)、pm(英文) %tz 相对于GMT RFC 82格式的数字时区偏移量 +0800 %tZ 时区缩写形式的字符串 CST %ts 1970-01-01 00:00:00至现在经过的秒数 1206426646 %tQ 1970-01-01 00:00:00至现在经过的毫秒数 1206426646456
-
举例:
public static void main(String[] args) { Date date = new Date(); System.out.println("时24小时制:"+String.format("%tH", date)); System.out.println("时12小时制:"+String.format("%tI", date)); System.out.println("分:"+String.format("%tM", date)); System.out.println("秒:"+String.format("%tS", date)); System.out.println("毫秒:"+String.format("%tL", date)); System.out.println("微秒:"+String.format("%tN", date)); System.out.println("时区偏移量:"+String.format("%tz", date)); System.out.println("时区缩写形式的字符串:"+String.format("%tZ", date)); System.out.println("1970-01-01 00:00:00至现在经过的秒数:"+String.format("%ts", date)); System.out.println("1970-01-01 00:00:00至现在经过的毫秒数:"+String.format("%tQ", date)); } //执行结果 时24小时制:15 时12小时制:03 分:40 秒:20 毫秒:710 微秒:710000000 时区偏移量:+0800 时区缩写形式的字符串:CST 1970-01-01 00:00:00至现在经过的秒数:1508917220 1970-01-01 00:00:00至现在经过的毫秒数:1508917220710 //CST可以为如下4个不同的时区的缩写: 美国中部时间:Central Standard Time (USA) UT-6:00 澳大利亚中部时间:Central Standard Time (Australia) UT+9:30 中国标准时间:China Standard Time UT+8:00 古巴标准时间:Cuba Standard Time UT-4:00 //0时区:以英国伦敦格林尼治天文台为零时区
-
- 24.5.1.3 常见的日期时间组合
-
常见的日期和时间组合的格式
转换符 说明 示例 %tF "年-月-日"格式(4位年份) 2008-03-25 %tD "月/日/年"格式(2位年份) 03-25-08 %tc 包括全部日期和时间信息 星期二 三月 25 13:37:22 CST 2008 %tr "时:分:秒 PM(AM)"格式(12小时制) 03:22:06 下午 %tT "时:分:秒"格式(24小时制) 15:22:06 %tR "时:分"格式(24小时制) 15:22
-
举例:
public static void main(String[] args) { Date date = new Date(); System.out.println("年-月-日格式(4位年份):"+String.format("%tF", date)); System.out.println("月/日/年格式(2位年份):"+String.format("%tD", date)); System.out.println("全部日期和时间信息:"+String.format("%tc", date)); System.out.println("时:分:秒 PM(AM)格式(12小时制):"+String.format("%tr", date)); System.out.println("时:分:秒格式(24小时制):"+String.format("%tT", date)); System.out.println("时:分格式(24小时制):"+String.format("%tR", date)); } //执行结果 年-月-日格式(4位年份):2017-10-25 月/日/年格式(2位年份):10/25/17 全部日期和时间信息:星期三 十月 25 16:12:33 CST 2017 时:分:秒 PM(AM)格式(12小时制):04:12:33 下午 时:分:秒格式(24小时制):16:12:33 时:分格式(24小时制):16:12
-
- 24.5.1.4 常规类型格式化
-
常规转换符
转换符 说明 示例 %c、%C 格式化为字符类型 'a' %d 格式化为十进制数 10 %o 格式化为八进制数 11 %x、%X 格式化为十六进制数 4b1
-
举例:
System.out.println("1000转化为十进制数:"+String.format("%d", 1000)); System.out.println("1000转化为八进制数:"+String.format("%o", 1000)); System.out.println("1000转化为十六进制数:"+String.format("%X", 1000)); System.out.println("100转化字符:"+String.format("%c", 100)); //执行结果 1000转化为十进制数:1000 1000转化为八进制数:1750 1000转化为十六进制数:3E8 100转化字符:d
-
- 24.5.1.1 日期格式化
24.6 正则表达式
-
24.6.1 什么是正则表达式:正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。目前,正则表达式已经在很多软件中得到广泛的应用,包括*nix(Linux, Unix等),HP等操作系统,PHP,C#,Java等开发环境,以及很多的应用软件中,都可以看到正则表达式的影子。
-
24.6.2 为什么使用正则表达式举例: 例:从命令行输入一个字符串,判断是不是合法的EMAIL地址,判断条件如下:
-
‘@’字符和‘.’字符至少应该出现一次;
-
‘@’字符在字符串中只能出现一次;
-
‘@’字符和‘.’字符都不能出现在字符串的最前面;
-
‘@’字符和‘.’字符都不能出现在字符串的最末尾;
-
‘.’字符不能出现在‘@’字符的前面;
-
‘@’字符和‘.’字符不能出现在相邻的位置(即‘@’字符和‘.’字符之间必须还有其他字符)。
String email = "1398274478@qq.com"; if (email.indexOf(".") != -1 && email.indexOf("@") != -1) { if (email.indexOf("@") == email.lastIndexOf("@")) { if (!(email.startsWith("@") || email.startsWith(".")) && !(email.endsWith("@") || email.endsWith("."))) { if (email.indexOf(".") > email.indexOf("@")) { if ((email.indexOf(".") - email.indexOf("@")) != 1) { System.out.println("合法的邮箱名:"+email); } else { System.out.println("‘@’字符和‘.’字符不能出现在相邻的位置(即‘@’字符和‘.’字符之间必须还有其他字符)。"); } } else { System.out.println("‘.’字符不能出现在‘@’字符的前面"); } } else { System.out.println("‘@’字符和‘.’字符都不能出现在字符串的最前面或末尾"); } } else { System.out.println("‘@’字符在字符串中只能出现一次"); } } else { System.out.println("‘@’字符和‘.’字符至少应该出现一次"); }
-
-
24.6.3 各个字符的含义:见文档:正则表达式手册.chm
-
24.6.4 使用举例:(使用的包:java.util.regex.Matcher;java.util.regex.Pattern;)
-
$ 匹配输入字符串的结尾位置。
//方法1: //1.使用Pattern调用compile(书写正则表达式规则)方法来书写正则表达式的规则 Pattern p = Pattern.compile("bug$"); //2.通过返回的Pattern调用他的matcher(输入要判断的字符串)方法来输入要判断的字符串。 Matcher m = p.matcher("bug"); //3.开始匹配 boolean b1 = m.matches(); //方法2: boolean b1 = Pattern.matches("bug$", "bug"); System.out.println("b1:"+b1);b1:true
-
* 匹配前面的子表达式零次或多次。
boolean b2 = Pattern.matches("(bu)*g", "bubububug"); System.out.println("b2:"+b2);b2:true boolean b2_1 = Pattern.matches("bu\\*g", "bu*g"); System.out.println("b2_1:"+b2_1);b2_1:true
-
( ) 标记一个子表达式的开始和结束位置。把括号中的内容作为一个整体。
boolean b3 = Pattern.matches("(bu*g)*g", "g"); System.out.println("b3:"+b3);b3:true
-
+ 匹配前面的子表达式一次或多次。
boolean b4 = Pattern.matches("b+g", "bbbbbbbbg"); System.out.println("b4:"+b4);b4:true
-
. 匹配除换行符 \n之外的任何单字符。
boolean b5 = Pattern.matches(".g\\.", "qg."); System.out.println("b5:"+b5);b5:true
-
? 匹配前面的子表达式零次或一次。
boolean b6 = Pattern.matches("(bu)?g", "bug"); System.out.println("b6:"+b6);b6:true
-
\ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。
boolean b7 = Pattern.matches("\\.\\*\\(\\)", ".*()"); System.out.println("b7:"+b7);b7:true
-
^ 匹配输入字符串的开始位置。
boolean b8 = Pattern.matches("^once", "once upon a time"); System.out.println("b8:"+b8);b8:false boolean b8_1 = Pattern.matches("^[abc]", "c"); System.out.println("b8_1:"+b8_1);b8_1:true boolean b8_2 = Pattern.matches("[^abc]", "d");//必须写abc之外的 System.out.println("b8_2:"+b8_2);b8_2:true
-
| 指明两项之间的一个选择。
boolean b9 = Pattern.matches("a|b|123", "a"); System.out.println("b9:"+b9);b9:true
-
{n} n 是一个非负整数。匹配确定的 n 次。
boolean b10 = Pattern.matches("a{5}", "aaaaa"); System.out.println("b10:"+b10);b10:true
-
{n,} n 是一个非负整数。至少匹配n 次。
boolean b11 = Pattern.matches("b{5,}", "bbbbbbbbbbbb"); System.out.println("b11:"+b11);b11:true
-
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。
boolean b12 = Pattern.matches("c{2,5}", "cccccc"); System.out.println("b12:"+b12);b12:false
-
各种操作符的运算优先级:相同优先级的从左到右进行运算,不同优先级的运算先高后低。各种操作符的优先级从高到低如下:
操作符 描述 \ 转义符 (), (?:), (?=), [] 圆括号和方括号 *, +, ?, {n}, {n,}, {n,m} 限定符 ^, $, \anymetacharacter 位置和顺序 | “或”操作
-
\d 匹配这个位置是0-9的数,等价于[0123456789]、[0-9]。\D是取反,相当于:[^0-9]
boolean b13 = Pattern.matches("\\d", "5"); System.out.println("b13="+b13);
-
[a-zA-Z]匹配字母az,AZ,[^a-zA-Z] 匹配不是字母
boolean b14 = Pattern.matches("[a-zA-Z]", "A"); System.out.println("b14="+b14);
-
\w 匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_]。\W是取反,相当于[^A-Za-z0-9_]。
boolean b15 = Pattern.matches("\\w", "a"); System.out.println("b15="+b15);
-
匹配输入的账号字符串是否为字母或数字,长度为6-10
boolean b16 = Pattern.matches("([a-zA-Z0-9]){6,10}", "qwer123"); System.out.println("b16="+b16);
-
使用正则表达式来实现上述例子的邮箱匹配
boolean b17 = Pattern.matches("\\w+@\\w{1,5}\\.\\w{2,3}", "qwer123@qq.com"); System.out.println("b17="+b17);
-
-
24.6.5 最全的常用正则表达式大全——包括校验数字、字符、一些特殊的需求等
-
校验数字的表达式
1. 数字:^[0-9]*$ 2. n位的数字:^\d{n}$ 3. 至少n位的数字:^\d{n,}$ 4. m-n位的数字:^\d{m,n}$ 5. 零和非零开头的数字:^(0|[1-9][0-9]*)$ 6. 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$ 7. 带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$ 8. 正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$ 9. 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$ 10. 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$ 11. 非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$ 12. 非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$ 13. 非负整数:^\d+$ 或 ^[1-9]\d*|0$ 14. 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$ 15. 非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$ 16. 非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$ 17. 正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$ 18. 负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$ 19. 浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
-
校验字符的表达式
1. 汉字:^[\u4e00-\u9fa5]{0,}$ 2. 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$ 3. 长度为3-20的所有字符:^.{3,20}$ 4. 由26个英文字母组成的字符串:^[A-Za-z]+$ 5. 由26个大写英文字母组成的字符串:^[A-Z]+$ 6. 由26个小写英文字母组成的字符串:^[a-z]+$ 7. 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$ 8. 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$ 9. 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$ 10. 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$ 11. 可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+ 12. 禁止输入含有~的字符:[^~\x22]+
-
特殊需求表达式
1. Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$ 2. 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.? 3. InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ 4. 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$ 5. 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$ 6. 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7} 7. 身份证号(15位、18位数字):^\d{15}|\d{18}$ 8. 短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$ 9. 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$ 10. 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$ 11. 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$ 12. 日期格式:^\d{4}-\d{1,2}-\d{1,2} 13. 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$ 14. 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$ 15. 钱的输入格式: 16. 有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$ 17. 这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$ 18. 一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$ 19. 这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$ 20. 必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$ 21. 这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$ 22. 这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$ 23. 1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$ 24. 备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里 25. xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$ 26. 中文字符的正则表达式:[\u4e00-\u9fa5] 27. 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)) 28. 空白行的正则表达式:\n\s*\r (可以用来删除空白行) 29. HTML标记的正则表达式:<(\S*?)[^>]*>.*?</\1>|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力) 30. 首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式) 31. 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始) 32. 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字) 33 IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用) 34 IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))
-
24.7 字符串生成器
-
24.7.1 StringBuilder的作用:当我们使用String对象的+号拼接字符串时,会在内存中穿件新的字符串对象。如果重复地对字符串进行修改,将极大的增加系统开销。所以增加了StringBuilder可变的字符序列,大大提高了频繁增加字符串的效率。
public static void main(String[] args) { //1.使用String拼接字符串 String str = ""; //获取当前的毫秒数 long startTime = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { str += i; } //获取运行拼接字符串操作之后的当前时间 long endTime = System.currentTimeMillis(); long time = endTime - startTime; System.out.println("String拼接字符串所消耗的时间="+time); //2.使用StringBuilder拼接字符串 StringBuilder sbu = new StringBuilder(""); startTime = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { sbu.append(i); } endTime = System.currentTimeMillis(); time = endTime - startTime; System.out.println("StringBuilder拼接字符串所消耗的时间="+time); } //执行结果 String拼接字符串所消耗的时间=197 StringBuilder拼接字符串所消耗的时间=0
结论:String拼接字符串的时间明显要多余StringBuilder的时间,所以String相当于创建了10000个新的对象,StringBuilder只会创建一个对象。
-
24.7.2 StringBuilder中的方法:新创建的StringBuilder对象初始容量是16个字符,可以自行指定初始长度。如果附加的字符超过可容纳的长度,则StringBuilder对象将自动增加长度以容纳被附加的字符。若要使用StringBuilder最后输出字符串结果,可以使用toString()方法。
-
append(content):该方法用于向字符串生成器中追加内容,通过该方法的多个重载形式,可以接收任何类型的数据。其中:content:可以是任何形式的数据或者其他对象。
-
insert(int offset, arg):该方法用于想字符串生成器中的指定位置插入数据内容。其中:offset:字符串生成器的位置。0~此序列的长度。arg:可以是任何形式的数据或者其他对象。
StringBuilder sbu = new StringBuilder("hello"); sbu.insert(1, "world"); System.out.println(sbu.toString()); //执行结果 hworldello
-
delete(int start, int end):移除此序列的子字符串中的字符。其中:start:将要删除字符串的起点位置。end:将要删除字符串的终点位置。如果start与end相等,则不发生更改。
StringBuilder sbu = new StringBuilder("hello"); sbu.delete(0, 2); System.out.println(sbu.toString()); //执行结果 llo
-
sbu.setLength(int len);//设置当前StringBuilder对象的长度。
sbu.setLength(0);//设置当前StringBuilder对象的长度
-
reverse():将此字符序列用其反转形式取代。
-
-
24.7.3 StringBuffer类:StringBuffer类与StringBuilder类的作用是一样的,区别是StringBuffer类是线程安全的,StringBuilder类是线程不安全的。线程安全与不安全以后讲。
24.8 作业
- String类:
- 编写一个Java程序,完成以下功能:
- 声明一个名为s的String对象,并使它的内容是"Call me Accp";
- 打印整个字符串。
- 使用length()方法打印字符串的长度。
- 使用charAt()方法打印字符串的第一个字符。
- 使用charAt()方法和length()打印字符串的最后一个字符。
- 使用indexOf()方法和substring()方法打印字符串的第一个单词。
- 编写一个Java程序,用于:
- 测试两个字符串String firstString="This is"和String secondString=“This is”;是否相等。
- 将"his father"与其中的firstString字符串连接。
- 用z替换新字符串中的i。
- 编写一个类,检查字符是否为合法的Java标识符:提示(自己查看JDK帮助):使用Character.isJavaIdentifierStart()和Character.isJavaIdentifierPart()方法。
- 构建一个Occurrences类,查找字符"e"在字符串"Seize the day"中出现的次数。
- 编写一个ExtractString类,从字符串"Seize the Day"中提取单词"the"和"Day".
- 编写一个Converse类,分别将作为命令行参数传递的整型值转换为二进制、十六进制以及八进制数值,(提示:自己查看JDK帮助,学习使用Integer类与String的format()方法完成此任务。)
- 定义一个字符串数组,用于保存命令行输入的字符串,要你找出所有图片格式的字符串。(如:.jpg,.bmp,.gif)。
- 编写类:CheckLetter,从命令行参数中读入一个字符串,检查该字符串中有多少个数字,英文字母,和其他字符.
- 回文串:编写类CheckPalindrome,从命令行参数中读入一个字符串,检查该字符串是否为回文串,回文串的特点是顺序读和倒序读都是一样。例如,mom、dad和atoyota都是回文串。(提示:可以使用StringBuffer类的倒置完成)。
- 定义一个字符串String str = “你a12好,c9我qwe是ss刘某某,来so自火星。”;去除掉字符串中的数字和字母,然后组成新的字符串。
- 编写一个Java程序,完成以下功能:
- 正则表达式:使用正则表达式实现邮箱、用户名、账号、密码、手机号、生日验证、是否为中文(常用汉字编码范围\u4e00-\u9fa5,双字节字符[^\x00-\xff])。