Java 第6章 字符串及应用.ppt
第6章字符串及应用 内容提要字符串是字符的序列,它是许多程序设计语言的基本数据结构。有些语言中的字符串是通过字符数组实现的(如C语言),Java语言是通过字符串类实现的。本章要点本章主要介绍String类和StringBuilder类、命令行参数和正则表达式字符串类Java语言提供了三个字符串类:String类是不变字符串StringBuilder和StringBuffer是可变字符串这三种字符串都是16位的Unicode字符序列,并且这三个类都被声明为final,因此不能被继承。这三个类各有不同的特点,应用于不同场合。6.1 String类 6.1.1 创建String类对象 6.1.2 字符串类几个常用方法6.1.3 字符串查找6.1.4 字符串与数组之间的转换6.1.5 字符串的解析6.1.6 字符串比较6.1.7 String对象的不变性6.1.1 创建String类对象方法一:直接利用字符串字面量创建字符串对象,例如:String s=This is a Java string.;方法二:一般使用String类的构造方法创建一个字符串对象。String类有十多个重载的构造方法,可以生成一个空字符串,也可以由字符或字节数组生成字符串。常用的构造方法如下:6.1.1 创建String类对象public String():创建一个空字符串。public String(char value):使用字符数组中的字符创建字符串。public String(char value,int offset,int count):使用字符数组中offset为起始下标,count个字符创建一个字符串。public String(byte bytes):使用字节数组中的字符创建字符串。public String(byte bytes,int offset,int count):offset为数组元素起始下标,count为元素个数。使用这些字节创建字符串。6.1.1 创建String类对象public String(byte bytes,String charsetName):使用指定的字节数组构造一个新的字符串,新字符串的长度与字符集有关,因此可能与字节数组的长度不同。charsetName为使用的字符集名,如US-ASCII、ISO-8859-1、UTF-8、UTF-16等。如果使用了系统不支持的字符集,将抛出UnsupportedEncodingException异常。public String(String original):使用一个字符串对象创建字符串。public String(StringBuffer buffer):使用StringBuffer对象创建字符串。public String(StringBuilder buffer):使用StringBuilder对象创建字符串。6.1.1 创建String类对象下面的例子说明了使用字符串的构造方法创建字符串对象。程序6.1 StringDemo.java程序运行结果为:s1=ABCs2=中国s3=ABCs4=abcde6.1.2字符串类几个常用方法String类定义了许多方法,下面是几个最常用方法。public int length():返回字符串的长度,即字符串包含的字符个数。注意,对含有中文或其他语言符号的字符串,计算长度时,一个符号作为一个字符计数。public char charAt(int index):返回字符串中指定位置的字符,index表示位置,范围为0s.length()-1。public String concat(String str):将调用字符串与参数字符串连接起来,产生一个新的字符串。6.1.2字符串类几个常用方法public String substring(int beginIndex,int endIndex):从字符串的下标beginIndex开始到endIndex结束产生一个子字符串。public String substring(int beginIndex):从字符串的下标beginIndex开始到结束产生一个子字符串。public String replace(char oldChar,char newChar):将字符串中的所有oldChar字符改变为newChar字符,返回一个新的字符串。public String toUpperCase():将字符串转换成大写字母。public String toLowerCase():将字符串转换成小写字母。6.1.2字符串类几个常用方法public String trim():返回去掉了前后空白字符的字符串对象。public boolean isEmpty():返回该字符串是否为空(),如果length()的结果为0,方法返回true,否则返回false。6.1.2字符串类几个常用方法下面程序要求从键盘输入一个字符串,判断该字符串是否是回文串。一个字符串,如果从前向后读和从后向前读都一样,则称该串为回文串。例如,“mom”和“上海海上”都是回文串。算法思想:对于一个字符串,先判断该字符串的算法思想:对于一个字符串,先判断该字符串的第一个字符和最后一个字符是否相等,如果相等,第一个字符和最后一个字符是否相等,如果相等,检查第二个字符和倒数第二个字符是否相等。这检查第二个字符和倒数第二个字符是否相等。这个过程一直进行,直到出现不相等的情况或者串个过程一直进行,直到出现不相等的情况或者串中所有字符都检测完毕,当字符串有奇数个字符中所有字符都检测完毕,当字符串有奇数个字符时,中间的字符不用检查。时,中间的字符不用检查。6.1.2字符串类几个常用方法 程序6.2 CheckPalindrome.java 6.1.3字符串查找String类提供了从字符串中查找字符和子串的方法,如下所示。public int indexOf(int ch):查找字符ch第一次出现的位置。如果查找不成功则返回-1,下述方法相同。public int indexOf(int ch,int fromIndex):查找字符ch从fromIndex开始第一次出现的位置(在原字符串中的下标)。public int lastIndexOf(int ch):查找字符ch最后一次出现的位置。public int lastIndexOf(int ch,int endIndex):查找字符ch到endIndex为止最后一次出现的位置。6.1.3字符串查找public int indexOf(String str,int fromIndex):查找字符串str从fromIndex开始第一次出现的位置(在原字符串中的下标)。public int indexOf(String str):查找字符串str第一次出现的位置。public int lastIndexOf(String str):查找字符串str最后一次出现的位置public int lastIndexOf(String str,int endIndex):查找字符串str到endIndex为止最后一次出现的位置(在原字符串中的下标)。6.1.3字符串查找程序6.3 StringSearch.java 6.1.4 字符串与数组之间的转换字符串与数组之间的转换字符串不是数组,但是字符串能够转换成数组,反之亦然。String类提供了下列方法将字符串转换成数组:public char toCharArray():将字符串中的字符转换为字符数组。public byte getBytes():使用平台默认的字符集将字符串编码成字节序列并将结果存储到字节数组中。6.1.4 字符串与数组之间的转换字符串与数组之间的转换public byte getBytes(String charsetName):使用指定的字符集将字符串编码成字节序列 并将结果存储到字节数组中。该方法抛出java.io.UnsupportedEncodingException异常。public void getChars(int srcBegin,int srcEnd,char dst,int dstBegin):将字符串中从起始位置(srcBegin)到结束位置(srcEnd)之间的字符复制到字符数组dst中,dstBegin为目标数组的起始位置。6.1.4 字符串与数组之间的转换字符串与数组之间的转换下面代码使用toCharArray()方法将字符串转换为字符数组,使用getChars()方法将字符串的一部分复制到字符数组中。String s=new String(This is a Java string.);char chars=s.toCharArray();System.out.println(chars);/This is a Java string.char subs=new char4;s.getChars(10,14,subs,0);System.out.println(subs);/Java6.1.5 字符串的解析字符串的解析String类提供了一个split()方法,它实现将一个字符串分解成子字符串或令牌(Token)。该方法使用正则表达式指定分隔符,该方法 有下面两种格式:public String split(String regex,int n)参数regex表示正则表达式,n表示模式应用的次数。如果n的值为0,则模式将应用尽可能多的次数,末尾的空字符串被丢弃。如果n的值大于0,则模式至多被应用n-1次,结果数组的长度不大于n,数组的最后一项将包含除最后一个匹配的分隔符外的所有输入内容。如果n的值小于0,则模式将应用尽可能多的次数。6.1.5 字符串的解析字符串的解析public String split(String regex):与上述方法n为0的情况相同。public boolean matches(String regex):返回字符串是否与给定的正则表达式匹配。在split()方法中指定的正则表达式“,.”的含义是使用空格、逗号或句点为分隔符解析字符串。关于正则表达式请参考6.4节。6.1.5 字符串的解析字符串的解析程序6.4 SplitDemo.java public class SplitDemo public static void main(Stringargs)String ss=one little,two little,three little.;String str=ss.split(,.);for(String s:str)System.out.println(s);System.out.println(ss.matches(.*little.*);/输出true 6.1.6 字符串比较字符串比较在Java程序中,经常需要比较两个字符串是否相等、或比较两个字符串的大小,下面介绍如何比较字符串。1.字符串相等的比较要比较两个字符串是否相等,你可能想到用“=”号来比较,如下代码所示:String s1=new String(Hello);String s2=new String(Hello);System.out.println(s1=s2);然而,上面代码的输出结果为false。这是因为在Java语言中用“=”比较引用类型的数据(对象)时,比较的是引用(地址)是否相等。6.1.6 字符串比较字符串比较只有两个引用指向同一个对象时,结果才为true。上面使用构造方法创建的两个对象是不同的,因此s1和s2的引用是不同的,如图6.1(a)所示。6.1.6 字符串比较字符串比较再看下面一段代码:String s1=Hello;String s2=Hello;System.out.println(s1=s2);这次输出结果为true。这两段代码的不同之处就在于创建s1、s2对象的代码不同。这里的s1、s2是用字符串常量创建的两个对象。字符串常量存储和对象存储不同,字符串常量是存储在常量池中,对内容相同的字符串常量在常量池中只有一个副本,因此s1和s2是指向同一个对象,如图6.1(b)所示。6.1.6 字符串比较字符串比较由上面可以看到,“=”用来比较两个引用值是否相等,如果要比较两个对象的内容是否相等,可以使用String类的equals()方法或equalsIgnoreCase()方法。public boolean equals(String anotherString)public boolean equalsIgnoreCase(String anotherString)使用第二个方法比较时将忽略大小写。对于上面两种情况,表达式:s1.equals(s2)的结果都为true,因为s1、s2的内容相等。6.1.6 字符串比较字符串比较2.字符串大小的比较 使用equals()方法只能比较字符串的相等与否,要比较大小,可以使用String类的compareTo()方法或compareToIgnoreCase()方法,格式为:public int compareTo(String anotherString)public int compareToIgnoreCase(String anotherString)第二个方法比较时忽略大小写。该方法将当前字符串与参数字符串比较,并返回一个整数值。6.1.6 字符串比较字符串比较字符串比较使用字符的Unicode码值进行比较。若当前字符串小于参数字符串,方法返回值小于0,若当前字符串大于参数字符串,方法返回值大于0,若当前字符串等于参数字符串,方法返回值等于0。例如,表达式“ABC.compareTo(ABD)的返回值为-1。注意:字符串不能使用、=、java HelloProgram How are you!程序运行结果为:How are you!6.2 命令行参数Java解释器根据传递的参数个数确定数组args的长度,如果给出的参数少于引用的元素,则抛出ArrayIndexOutOfBoundsException运行时异常,例如:D:studyjava HelloProgram How are 上述命令中只提供了两个命令行参数,创建的args数组长度为2,而程序中访问了第3个元素(args2),故产生运行时异常。6.2 命令行参数命令行参数传递的是字符串,若将其作为数值处理,需要进行转换。下面的程序要求从命令行输入3个整数,输出最大值和最小值。程序6.8 ThreeInteger.javapublic class ThreeInteger public static void main(String args)int max,min,a,b,c;a=Integer.parseInt(args0);/将字符串转换为整数 b=Integer.parseInt(args1);6.2 命令行参数 c=Integer.parseInt(args2);max=Math.max(Math.max(a,b),c);/求a,b,c的最大值 min=Math.min(Math.min(a,b),c);System.out.println(max=+max);System.out.println(min=+min);运行该程序需要在命令行给出参数,如下所示:D:studyjava ThreeInteger 23 -234 100程序运行结果为:max=100 min=-2346.3 StringBuilder类 StringBuilder和StringBuffer类都表示可变字符串,即这两个类的对象内容是可以修改的。6.3.1 创建StringBuilder对象 6.3.2 StringBuilder的访问和修改6.3.3 运算符“+”的重载6.3.1 创建StringBuilder对象StringBuilder类是Java 5新增加的,它表示可变字符串。StringBuilder类常用的构造方法有下面3个。public StringBuilder():创建一个没有字符的字符串缓冲区,初始容量为16个字符。此时length()方法的值为0,而capacity()方法的值为16。6.3.1 创建StringBuilder对象public StringBuilder(int capacity):创建一个没有字符的字符串缓冲区,capacity为指定的初始容量。public StringBuilder(String str):利用一个已存在的字符串对象str创建一个字符串缓冲区对象,另外再分配16个字符的缓冲区。StringBuilder类除定义了length()、charAt()、indexOf()、getChars()等方法外,还提供了下列常用方法:public int capacity():返回当前的字符串缓冲区的总容量。public void setCharAt(int index,char ch):用ch修改指定位置的字符。public StringBuilder deleteCharAt(int index):删除指定位置的字符。public StringBuilder append(String str)在当前的字符串的末尾添加一个字符串。6.3.2 StringBuilder的访问和修改6.3.2 StringBuilder的访问和修改 append方法有一系列的重载方法,参数可以是boolean、char、int、long、float、double、char等任何数据类型。public StringBuilder insert(int offset,String str):在当前字符串的指定位置插入一个字符串。这个方法个也有多个重载的方法,参数可以是boolean、char、int、long、float、double、char等类型。public StringBuilder delete(int start,int end):删除从start开始到end(不包括end)之间的字符。public StringBuilder replace(int start,int end,String str):用字符串str替换从start开始到end(不包括end)之间的字符。6.3.2 StringBuilder的访问和修改public StringBuilder reverse():将字符串的所有字符反转。public String substring(int start):返回从start开始到字符串末尾的子字符串。public String substring(int start,int end):返回从start开始到end(不包括end)之间的子字符串。public void setLength(int newLength):设置字符序列的长度。如果newLength小于原字符串的长度,字符串将被截短,如果newLength大于原字符串的长度,字符串将使用空字符(u0000)扩充。6.3.2 StringBuilder的访问和修改程序6.9 StringBuilderDemo.java 该程序演示了StringBuilder对象及其方法的使用。public class StringBuilderDemo public static void main(String args)StringBuilder ss=new StringBuilder(Hello);System.out.println(ss.length();System.out.println(ss.capacity();ss.append(Java);System.out.println(ss);System.out.println(ss.insert(5,);System.out.println(ss.replace(6,10,World!);System.out.println(ss.reverse();6.3.2 StringBuilder的访问和修改程序运行结果为:521HelloJavaHello,JavaHello,World!dlroW,olleH 使用StringBuilder对象可以方便地对其修改,而不需要生成新的对象。6.3.3 运算符“+”的重载在Java语言中不支持运算符重载,但有一个特例,即“+”运算符(包括+=),它是唯一重载的运算符。该运算符除用于计算两个数之和外还用于连接两个字符串。当用“+”运算符连接的两个操作数其中有一个是String类型时,该运算即为字符串连接运算,如:int age=18;String s=He is+age+years old.;上述连接运算过程实际上是这样进行的:String s=new StringBuilder(He is).append(age).append(years old.).toString();6.3.3 运算符“+”的重载提示:Java还定义了StringBuffer类,它与StringBuilder类的主要区别是StringBuffer类的实例是线程安全的,而StringBuilder类的实例不是线程安全的。如果不需要线程同步,建议使用StringBuilder类。6.4 正则表达式 模式匹配在计算机中有着广泛的应用。Java语言通过Pattern和Matcher类也提供了强大的模式匹配的功能。6.4.1 模式匹配6.4.2 Pattern类6.4.3 Matcher类6.4.4 量词和捕获组 6.4.1 模式匹配1.什么是模式匹配 看一个简单的例子。假如有一个字符串“a22apple45ab”,若要在该字符串中查找“apple”。可以找到一个匹配。我们应该指定一个模式串“.*apple.*”,字符串“a22apple45ab”称为输入串。6.4.1 模式匹配为了实现复杂的模式匹配,模式串的构造应该遵循某种规则,这样的模式称为正则表达式(regular expressions)。在Java语言中通过java.util.regex包中的类实现正则表达式的模式匹配。该包中提供了Pattern、Matcher和PatternSyntax Exception类与MatchResult接口。Pattern对象就是一个正则表达式的编译表示形式。Pattern类没有定义构造方法,要得到该类对象,需要调用该类的静态方法compile()。该方法接受一个字符串参数,该字符串必须是一个正则表达式,该方法返回Pattern对象。6.4.1 模式匹配Matcher类的实例用来按照给定的模式匹配一个输入字符序列。Matcher类也没有定义public的构造方法,需要调用Pattern类的实例方法matcher()返回Matcher类的一个实例,该方法接受一个字符序列,它就是模式要与其匹配的输入串。接下来,调用Matcher类的实例方法matches()来判断是否有一个匹配。6.4.1 模式匹配面是一个典型的调用顺序:Pattern p=Ppile(.*apple.*);Matcher m=p.matcher(a22apple45ab);boolean b=m.matches();/b的结果为true,说明有一个匹配6.4.1 模式匹配当正则表达式只使用一次时,使用Pattern类中定义的matches()方法更方便,该方法同时编译模式并与输入字符串匹配,语句如下:boolean b=Pattern.matches(.*apple.*,a22apple45ab);Pattern类的实例是不可变的对象并且在被多个线程使用时是安全的,而Matcher实例不是安全的。6.4.1 模式匹配2.模式的指定最简单的模式可以只包含一个字符。要指定多个字符或字符范围,需要使用方括号将字符括起来。例如,jaz匹配j、a、z,而j-z匹配j到z的字符,也可以使用否定符号,如abc表示匹配除a、b、c以外的字符。表6.1列出了一些示例。6.4.1 模式匹配表6.1 正则表达式示例正则表达式说 明abc匹配a,b,或cabc匹配除a、b、c以外的字符a-zA-Z匹配a到z或A到Z之间的字符a-dm-pa到d或m到p(并)a-z&defd,e,或f(交)a-z&bc除b,c以外a到z:ad-z(差)a-z&m-pa到z中除m到p以外的字符:a-lq-z(差)6.4.1 模式匹配在模式串中还可以使用一些预定义字符,称为元字符,如表6.2所示。表6.2 常用的元字符元字符说 明.匹配任何单个字符d一位数字:0-9D一位非数字:0-9s空格字符:tnx0BfrS非空格字符:sw一个单词字符:a-zA-Z_0-9W一个非单词字符:w6.4.1 模式匹配下面的程序用来测试对于一个给定的正则表达式,是否能在输入串中找到匹配,以及匹配的开始和结束索引。程序6.10 RegexTest.java 6.4.1 模式匹配运行该程序,然后输入字符串“2nabsjdkabc”,正则表达式输入“ab”,程序的运行结果为:Enter input string:2nabsjdkabc2nabsjdkabcEnter your regex:ababI found the text ab starting at index 2 and ending at index 4.I found the text ab starting at index 8 and ending at index 10.上述结果表示,在“2nabsjdkabc”找到了两个“ab”,第一个开始位置为0,结束位置为4,第二个开始位置为8,结束位置为10,。这里位置是从0开始的。6.4.2 Pattern类Pattern类的实例是用字符串的形式表示的正则表达式,语法类似于Perl语言的语法。使用Pattern类的静态方法compile()方法构造模式对象,该方法有两种形式:public static Pattern compile(String regex):将给定的正则表达式编译成Pattern类的一个实例,如果表达式语法错误,将抛出PatternSyntaxException运行时异常。public static Pattern compile(String regex,int flags):flags参数用来指定匹配如何进行,它使用Pattern类的一个常量。例如,CASE_INSENSITIVE表示启用不区分大小写的匹配,其他常量请参阅API文档。6.4.2 Pattern类Pattern类的其他常用方法有:public String pattern():返回该模式对象的正则表达式字符串。public Matcher matcher(CharSequence input):创建按照模式与给定的输入字符序列匹配的Matcher对象。public static boolean matches(String regex,CharSequence input):对给定的正则表达式编译并与输入序列匹配,如果匹配成功返回true。当不需要重复使用匹配器时可以使用该方法6.4.2 Pattern类public String split(CharSequence input):使用该模式对象对输入字符序列拆分。public String split(CharSequence input,int limit):limit参数用于控制模式使用的次数,它将影响结果数组的长度。public int flags():返回该模式的匹配标志。public static String quote(String s):返回一个String对象,它可用来创建与s匹配的模式。public String toString():返回该模式对象的字符串表示。6.4.2 Pattern类下面程序使用逗号和空格创建一个模式,然后用其拆分一个字符串。程序6.11 Splitter.javaimport java.util.regex.*;public class Splitter public static void main(String args)throws Exception/创建一个模式对象Pattern p=Ppile(,s+);/使用模式对象对输入字符串分解String result=p.split(one,two,three four,five);for(int i=0;i result.length;i+)System.out.print(|+resulti+|,);程序运行结果为:|one|,|two|,|three|,|four|,|five|,6.4.3 Matcher类Matcher类的实例用来根据给定的模式匹配字符序列。通过调用模式对象的matcher()方法来得到一个Matcher类的对象。一旦得到一个Matcher类的对象,就可以使用下列方法执行匹配操作,这些方法返回值为boolean类型。6.4.3 Matcher类public boolean matches():尝试将整个输入序列与该模式进行匹配。如果返回true,则匹配成功,匹配成功后可以使用start()方法、end()方法和group()方法获得更多信息。public boolean lookingAt():尝试从区域开始处的输入序列与该模式进行匹配。与matches()方法不同的是它不需要匹配整个输入序列。public boolean find():尝试查找输入序列中与该模式匹配的下一个序列。该方法从序列的开头开始匹配,或者,如果上一次find()方法是成功的,并且匹配器没有重置,则本次匹配从上次匹配中还没进行匹配的第一个字符开始6.4.3 Matcher类public boolean find(int start):重置该匹配器,然后尝试从指定索引位置开始查找与该模式匹配的下一个子序列。如果查找成功,则可以使用下列方法返回有关匹配的更多信息。public int start():返回上次成功匹配的开始索引值。public int end():返回匹配的序列中最后一个字符的索引值加1的值。public String group():返回匹配成功的子序列,即由start和end定义的子字符串。public int groupCount():返回该匹配器模式中的捕获组数。组号范围从0开始,到这个组数减1的值。6.4.3 Matcher类public String group(int group):返回上次匹配中与给定组匹配的输入子序列。第0组表示整个匹配模式,所以group(0)与group()等价。public int start(int group):返回上次匹配中给定组的开始索引值。public int end(int group):返回与给定组匹配的序列中最后一个字符的索引值加1。一旦开始进行匹配,可以使用下列方法改变匹配器的状态:public Matcher reset():重置匹配器。该方法将丢弃该匹配器的所有状态信息,并将其追加位置重置为0。该方法返回的Matcher对象就是调用该方法的Matcher对象。6.4.3 Matcher类public Matcher reset(CharSequence input):将该匹配器重置为使用新的输入序列。public Matcher usePattern(Pattern pattern):将该匹配器使用的模式重新设置为传递来的模式pattern。Matcher类也定义了使用新字符串替换匹配的序列的方法,如下所示:public String replaceFirst(String replacement):将与该匹配器的模式匹配的第一个字符序列替换成replacement字符串,并返回结果。该方法将首先重置匹配器,操作完成后不重置匹配器。6.4.3 Matcher类public String replaceAll(String replacement):将所有与该匹配器的模式匹配的字符序列都替换成replacement字符串,并返回结果。该方法将首先重置匹配器,操作完成后不重置匹配器。public Matcher appendReplacement(StringBuffer buf,String replacement):首先将当前追加位置和匹配位置之间的字符添加到字符串缓冲区中,接着添加replacement字符串,最后将匹配器的追加位置改为匹配字符序列之后的位置。public StringBuffer appendTail(StringBuffer buf):将从当前追加位置开始直到字符序列结尾为止的所有字符添加到字符串缓冲区中,最后返回该缓冲区对象。6.4.3 Matcher类程序6.12 Replacement.javaimport java.util.regex.*;public class Replacement public static void main(String args)throws Exception/创建一个匹配cat的模式对象Pattern p=Ppile(cat);/使用输入字符串创建一个匹配器对象Matcher m=p.matcher(One cat,two cats in the yard);StringBuffer sb=new StringBuffer();boolean result=m.find();6.4.3 Matcher类/循环将模式替换为新字符串while(result)m.appendReplacement(sb,dog);result=m.find();/将最后片段添加到新字符串中m.appendTail(sb);System.out.println(sb.toString();程序运行结果为:One dog,two dogs in the yard6.4.4 量词和捕获组1.量词量词(quantifiers)用来指定模式在字符串中出现的次数。有3种类型的量词,贪婪(greedy)量词、勉强(reluctant)量词和具有(possessive)量词,如表6.3所示。表的前3列给出了3种不同类型的量词,它们的用法不同。首先,来了解一下元字符的含义。6.4.4 量词和捕获组表6.3 正则表达式的量词贪婪量词勉强量词具有量词模式X出现的次数X?X?X?+X出现0次或1次X*X*?X*+X出现0次或多次X+X+?X+X出现1次或多次XnXn?Xn+X恰好出现n次Xn,Xn,?Xn,+X至少出现n次Xn,mXn,m?Xn,m+X至少出现n次,但不超过m次6.4.4 量词和捕获组最一般的量词是n,m,n和m都是整数。Xn,m在字符串中X至少重复n次,但不超过m次。例如,与X3,5匹配的字符串包括XXX、XXXX和XXXXX,但不包括X、XX和XXXXXX使用贪婪量词,匹配器首先将整个输入串读入。如果匹配失败,它将回退一个字符,检查匹配,直到没有字符为止。使用勉强量词,匹配器首先读入输入串的一个字符。如果匹配失败,它将添加一个后续字符,然后再检查。重复该过程,直到读完所有字符为止。使用具有量词与前两者不同,它使匹配器读取整个输入串,然后停止。6.4.4 量词和捕获组表6.4说明了三种量词的不同。输入串为“whellowwwhellowww”。表6.4 三种量词使用比较 正则表达式结 果.*hello 找到文本“whellowwwhello”,开始索引为0,结束索引为14.*?hello 找到文本“whello”,开始索引为0,结束索引为6和文本“wwwhello”,开始索引为6,结束索引为14.*+hello 没有找到匹配6.4.4 量词和捕获组2.捕获组上述操作也可用于一组字符上,这称为捕获组。一个捕获组是将一组字符作为一个单元处理。例如,(java)是一个捕获组,这里java是一个单元,javajava属于(java)*正则表达式。在输入串中与捕获组匹配的部分将被