第二十四章_字符串操作类

第二十四章 字符串操作类


提纲

  • 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.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小时。
      
    • 结论:

      1. 当其他类型与字符串连接时会自动调用toString方法,将其转换成字符串形式,然后参与连接。
      2. 只要是“+”运算符左右其中一个操作数是字符串,编译器就会把另一个操作数转换成字符串形式。
      3. 如果想要两个数字相加的结果应该使用括号将它们括起来。因为运算符中圆括号的优先级最高,所以会先执行圆括号中的内容再与其他字符串相连接。

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.6 正则表达式

  • 24.6.1 什么是正则表达式:正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。目前,正则表达式已经在很多软件中得到广泛的应用,包括*nix(Linux, Unix等),HP等操作系统,PHP,C#,Java等开发环境,以及很多的应用软件中,都可以看到正则表达式的影子。

  • 24.6.2 为什么使用正则表达式举例: 例:从命令行输入一个字符串,判断是不是合法的EMAIL地址,判断条件如下:

    1. ‘@’字符和‘.’字符至少应该出现一次;

    2. ‘@’字符在字符串中只能出现一次;

    3. ‘@’字符和‘.’字符都不能出现在字符串的最前面;

    4. ‘@’字符和‘.’字符都不能出现在字符串的最末尾;

    5. ‘.’字符不能出现在‘@’字符的前面;

    6. ‘@’字符和‘.’字符不能出现在相邻的位置(即‘@’字符和‘.’字符之间必须还有其他字符)。

       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:
       //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
      
    2. * 匹配前面的子表达式零次或多次。

       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
      
    3. ( ) 标记一个子表达式的开始和结束位置。把括号中的内容作为一个整体。

       boolean b3 = Pattern.matches("(bu*g)*g", "g");
       System.out.println("b3:"+b3);b3:true
      
    4. + 匹配前面的子表达式一次或多次。

       boolean b4 = Pattern.matches("b+g", "bbbbbbbbg");
       System.out.println("b4:"+b4);b4:true
      
    5. . 匹配除换行符 \n之外的任何单字符。

       boolean b5 = Pattern.matches(".g\\.", "qg.");
       System.out.println("b5:"+b5);b5:true
      
    6. ? 匹配前面的子表达式零次或一次。

       boolean b6 = Pattern.matches("(bu)?g", "bug");
       System.out.println("b6:"+b6);b6:true
      
    7. \ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。

       boolean b7 = Pattern.matches("\\.\\*\\(\\)", ".*()");
       System.out.println("b7:"+b7);b7:true
      
    8. ^ 匹配输入字符串的开始位置。

       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
      
    9. | 指明两项之间的一个选择。

       boolean b9 = Pattern.matches("a|b|123", "a");
       System.out.println("b9:"+b9);b9:true
      
    10. {n} n 是一个非负整数。匹配确定的 n 次。

      boolean b10 = Pattern.matches("a{5}", "aaaaa");
      System.out.println("b10:"+b10);b10:true
      
    11. {n,} n 是一个非负整数。至少匹配n 次。

      boolean b11 = Pattern.matches("b{5,}", "bbbbbbbbbbbb");
      System.out.println("b11:"+b11);b11:true
      
    12. {n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。

      boolean b12 = Pattern.matches("c{2,5}", "cccccc");
      System.out.println("b12:"+b12);b12:false
      
    13. 各种操作符的运算优先级:相同优先级的从左到右进行运算,不同优先级的运算先高后低。各种操作符的优先级从高到低如下:

      操作符 	 					描述 
      \ 		 					 转义符 
      (), (?:), (?=), []  	   圆括号和方括号 
      *, +, ?, {n}, {n,}, {n,m}    限定符 
      ^, $, \anymetacharacter    位置和顺序 
      | 						    “或”操作 
      
    14. \d 匹配这个位置是0-9的数,等价于[0123456789]、[0-9]。\D是取反,相当于:[^0-9]

      boolean b13 = Pattern.matches("\\d", "5");
      System.out.println("b13="+b13);
      
    15. [a-zA-Z]匹配字母az,AZ,[^a-zA-Z] 匹配不是字母

      boolean b14 = Pattern.matches("[a-zA-Z]", "A");
      System.out.println("b14="+b14);
      
    16. \w 匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_]。\W是取反,相当于[^A-Za-z0-9_]。

      boolean b15 = Pattern.matches("\\w", "a");
      System.out.println("b15="+b15);
      
    17. 匹配输入的账号字符串是否为字母或数字,长度为6-10

      boolean b16 = Pattern.matches("([a-zA-Z0-9]){6,10}", "qwer123");
      System.out.println("b16="+b16);
      
    18. 使用正则表达式来实现上述例子的邮箱匹配

      boolean b17 = Pattern.matches("\\w+@\\w{1,5}\\.\\w{2,3}", "qwer123@qq.com");
      System.out.println("b17="+b17);
      
  • 24.6.5 最全的常用正则表达式大全——包括校验数字、字符、一些特殊的需求等

    1. 校验数字的表达式

       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)$
      
    2. 校验字符的表达式

       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]+
      
    3. 特殊需求表达式

       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()方法。

    1. append(content):该方法用于向字符串生成器中追加内容,通过该方法的多个重载形式,可以接收任何类型的数据。其中:content:可以是任何形式的数据或者其他对象。

    2. insert(int offset, arg):该方法用于想字符串生成器中的指定位置插入数据内容。其中:offset:字符串生成器的位置。0~此序列的长度。arg:可以是任何形式的数据或者其他对象。

       StringBuilder sbu = new StringBuilder("hello");
       sbu.insert(1, "world");
       System.out.println(sbu.toString());
       //执行结果
       hworldello
      
    3. delete(int start, int end):移除此序列的子字符串中的字符。其中:start:将要删除字符串的起点位置。end:将要删除字符串的终点位置。如果start与end相等,则不发生更改。

       StringBuilder sbu = new StringBuilder("hello");
       sbu.delete(0, 2);
       System.out.println(sbu.toString());
       //执行结果
       llo
      
    4. sbu.setLength(int len);//设置当前StringBuilder对象的长度。

       sbu.setLength(0);//设置当前StringBuilder对象的长度
      
    5. reverse():将此字符序列用其反转形式取代。

  • 24.7.3 StringBuffer类:StringBuffer类与StringBuilder类的作用是一样的,区别是StringBuffer类是线程安全的,StringBuilder类是线程不安全的。线程安全与不安全以后讲。


24.8 作业

  • String类:
    1. 编写一个Java程序,完成以下功能:
      • 声明一个名为s的String对象,并使它的内容是"Call me Accp";
      • 打印整个字符串。
      • 使用length()方法打印字符串的长度。
      • 使用charAt()方法打印字符串的第一个字符。
      • 使用charAt()方法和length()打印字符串的最后一个字符。
      • 使用indexOf()方法和substring()方法打印字符串的第一个单词。
    2. 编写一个Java程序,用于:
      • 测试两个字符串String firstString="This is"和String secondString=“This is”;是否相等。
      • 将"his father"与其中的firstString字符串连接。
      • 用z替换新字符串中的i。
    3. 编写一个类,检查字符是否为合法的Java标识符:提示(自己查看JDK帮助):使用Character.isJavaIdentifierStart()和Character.isJavaIdentifierPart()方法。
    4. 构建一个Occurrences类,查找字符"e"在字符串"Seize the day"中出现的次数。
    5. 编写一个ExtractString类,从字符串"Seize the Day"中提取单词"the"和"Day".
    6. 编写一个Converse类,分别将作为命令行参数传递的整型值转换为二进制、十六进制以及八进制数值,(提示:自己查看JDK帮助,学习使用Integer类与String的format()方法完成此任务。)
    7. 定义一个字符串数组,用于保存命令行输入的字符串,要你找出所有图片格式的字符串。(如:.jpg,.bmp,.gif)。
    8. 编写类:CheckLetter,从命令行参数中读入一个字符串,检查该字符串中有多少个数字,英文字母,和其他字符.
    9. 回文串:编写类CheckPalindrome,从命令行参数中读入一个字符串,检查该字符串是否为回文串,回文串的特点是顺序读和倒序读都是一样。例如,mom、dad和atoyota都是回文串。(提示:可以使用StringBuffer类的倒置完成)。
    10. 定义一个字符串String str = “你a12好,c9我qwe是ss刘某某,来so自火星。”;去除掉字符串中的数字和字母,然后组成新的字符串。
  • 正则表达式:使用正则表达式实现邮箱、用户名、账号、密码、手机号、生日验证、是否为中文(常用汉字编码范围\u4e00-\u9fa5,双字节字符[^\x00-\xff])。
  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值