黑马程序员-JAVA-字符串与正则表达式粗解
2015-04-17 17:08
246 查看
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
字符串作为人类语言在计算机编程语言中的抽象表达形式,其应用无疑是极其广泛的,几乎高级编程语言都从语义或者基本类型上提供了对字符串的支持。
用于处理字符串常用的正则表达式则于1.4已引入,其功能依赖Pattern以及Matcher类。
String类是Java中很特殊的一个引用类型,因为在不支持运算符重载的Java中,String是一个支持+运算符的类型,盖因String的应用之频繁使然。而且Object中有toString方法来实现引用对象到字符串的隐式转换,以支持String的+运算符。
String的构造方法支持从byte数组按编码字符集构造,从char数组组成,从int数组按 Unicode 代码点数组成,以及从StringBuilder,StringBuffer,String生成副本。
String类支持多种常用操作,包括查询字符,比较,连接,格式化,正则表达式匹配,置换,切割等等,可以显式获取原始类型和引用类型的字符串表达,其中引用类型是调用toString()。
下面是一些简单的例子:
线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符添加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比StringBuffer 要快。
结果如下
可以看出StringBuilder在单线程条件下大致比StringBuffer高20%性能。
正则表达式最早出现在Unix系统的sed和grep命令工具中,后来perl所发展出来的pare(Perl Compatible Regular Expression)建立了良好的规范,成为许多工具的所使用的正则表达式库。
正则表达式最常见的应用就是匹配:比如匹配某个特定字符串,那么就直接写上这个字符串
元字符:类似于Java的保留字,是提供正则表达式语义的特殊字符,如果要匹配元字符,那么可以使用转义元字符
需要注意的是在Java文件中
字符类:字符类并不是Java中的类,而是指能匹配的字符的集合。用
预定义字符类 :
POSIX 字符类,java.lang.Character 类,Unicode 块和类别的类,这些可以参见Java doc @see Pattern
边界匹配器
组 捕获组是从 1 开始从左到右的索引。组零表示整个模式。
简单来说组的编号可以这么看 0表示整个模式,而后指从左到右第几个左括号内就是第几组,右括号匹配即可。
得到Pattern对象之后可以对字符串对象进行匹配而得到结果Matcher对象,这个对象中包含了丰富的信息,比如是否匹配成功boolean matches()。
Pattern的标志构建和内嵌标志表达式
Pattern的compile方法还有个重载形式:
compile(String regex, int flags)
用于接受影响模式匹配方式的标志集。标志参数是一个位掩码,可以是下面公共静态字段中的任意一个:
通常是因为正则表达式语法有误。
Matcher可以执行3种匹配
1. 最常用的matches方法,返回是否整个字符串是否匹配。
2. lookingAt方法,从头部开始尝试匹配。
3. find方法,从没有被find匹配的第一个字符开始,这个方法可以多次匹配。
匹配的结果通过查询匹配器来获得:
group(int group) 返回在以前匹配操作期间由给定组捕获的输入子序列。
start 返回以前匹配的初始索引
start(int group) 返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引。
end 返回最后匹配字符之后的偏移量
end(int group) 返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。
字符串作为人类语言在计算机编程语言中的抽象表达形式,其应用无疑是极其广泛的,几乎高级编程语言都从语义或者基本类型上提供了对字符串的支持。
Java中的字符串处理
Java中的字符串相关类型主要有String,StringBuffer,StringBuilder。用于处理字符串常用的正则表达式则于1.4已引入,其功能依赖Pattern以及Matcher类。
String 类型
String是Java中对于字符串的基本抽象,其内部数据结构是UTF-BE编码的char类型数组,数组是定长的,而String的数据结构也设计为了不可变内容,对其操作修改即是创建新的String对象并赋值。String类是Java中很特殊的一个引用类型,因为在不支持运算符重载的Java中,String是一个支持+运算符的类型,盖因String的应用之频繁使然。而且Object中有toString方法来实现引用对象到字符串的隐式转换,以支持String的+运算符。
String的构造方法支持从byte数组按编码字符集构造,从char数组组成,从int数组按 Unicode 代码点数组成,以及从StringBuilder,StringBuffer,String生成副本。
String类支持多种常用操作,包括查询字符,比较,连接,格式化,正则表达式匹配,置换,切割等等,可以显式获取原始类型和引用类型的字符串表达,其中引用类型是调用toString()。
下面是一些简单的例子:
String的常用方法演示
//source String source="今天,IDE这个词和一些没有关连性的命令列工具(像vi" + "、emacs、make)是一种对照,虽然你可以把Unix当成是一个IDE," + "但是多数的程序开发人员会把IDE当成是一个可以完成各种开发工作的一个程序," + "这个IDE程序提供许多的功能,例如:制作、修改、编译、发布、调试。"; sp(source); //if? sp("startWith a ?:"+source.startsWith("a")); sp("endsWith 。 ?:"+source.endsWith("。")); sp("contains Unix ?:"+source.contains("Unix")); sp("isEmpty ?:"+source.isEmpty()); //+ operator sp(source+43243+false+932754295L+null+46468.74643+864.2f);//Primitive sp(source+"clause"+new Object()+Void.class);//reference //modify sp(source.toLowerCase()); sp(source.toUpperCase()); sp(source.trim().replace('一', '二')); //transform sp(source.toCharArray());
StringBuffer
可变,线程安全线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符添加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
StringBuilder
可变,线程不安全,效率略高于StringBuffer一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比StringBuffer 要快。
StringBuffer 和StringBuilder的演示
private static void testStringBuffer() { final int count=10000; prepareALOT(count); //append test StringBuffer sb=new StringBuffer(); long start,end; start=System.nanoTime(); for (int i = 0; i < ALOT.length; i++) { sb.append(ALOT[i]); } end=System.nanoTime(); sp("StringBuffer append cost:"+(end-start)); //edit test List<String> sf = Arrays.asList(Arrays.copyOf(ALOT, ALOT.length)); Collections.shuffle(sf); sb.reverse(); start=System.nanoTime(); for (int i = 0; i < count; i++) { sb.delete(i, i+5); sb.insert(i, sf.get(i)); } end=System.nanoTime(); sp("StringBuffer edit cost:"+(end-start)); } private static void testStringBuilder() { final int count=10000; prepareALOT(count); //append test StringBuilder sb=new StringBuilder(); long start,end; start=System.nanoTime(); for (int i = 0; i < ALOT.length; i++) { sb.append(ALOT[i]); } end=System.nanoTime(); sp("StringBuilder append cost:"+(end-start)); //edit test List<String> sf = Arrays.asList(Arrays.copyOf(ALOT, ALOT.length)); Collections.shuffle(sf); sb.reverse(); start=System.nanoTime(); for (int i = 0; i < count; i++) { sb.delete(i, i+5); sb.insert(i, sf.get(i)); } end=System.nanoTime(); sp("StringBuilder edit cost:"+(end-start)); } private static void prepareALOT(int count) { if(ALOT==null){ ALOT=new String[count]; }else if(ALOT.length!=count){ ALOT=new String[count]; }else{ return; } Random r=new Random(); for (int i = 0; i < ALOT.length; i++) { char[] c=new char[8]; for (int i2 = 0; i2 < c.length; i2++) { int rp = r.nextInt(52); if(rp>26){ c[i2]=(char)(rp+'a'-26); }else{ c[i2]=(char)(rp+'A'); } } ALOT[i]=new String(c); } } private static String[] ALOT;
结果如下
StringBuffer append cost:1588992 StringBuffer edit cost:217009831 StringBuilder append cost:913430 StringBuilder edit cost:169428186
可以看出StringBuilder在单线程条件下大致比StringBuffer高20%性能。
正则表达式
正则表达式简介
Regular Expression,通常简写做Regex,意思是“(某种)规则的表达式”在计算机范畴中,通常用来表示处理匹配字符串的按一定规则写的规则表达式,而这个表达式也是字符串。正则表达式最早出现在Unix系统的sed和grep命令工具中,后来perl所发展出来的pare(Perl Compatible Regular Expression)建立了良好的规范,成为许多工具的所使用的正则表达式库。
Java中的正则表达式
Java中的正则表达式在1.4引入后大大增强了Java处理字符串的可用度,这就简单介绍一下Java正则表达式的规则正则表达式最常见的应用就是匹配:比如匹配某个特定字符串,那么就直接写上这个字符串
元字符:类似于Java的保留字,是提供正则表达式语义的特殊字符,如果要匹配元字符,那么可以使用转义元字符
'\',API 所支持的元字符有:
([{\^-$|}])?*+.
需要注意的是在Java文件中
\是转义符,所以在Java文件中hardcode一个Regex转义符
\需要连续2个
\\,第一个被javac处理,而第二个才能被正则表达式所识别
字符类:字符类并不是Java中的类,而是指能匹配的字符的集合。用
[]来包括字符表示一个简单类,字符或字符类并列表示合集,
|表示或者,
-表示连续,^表示取反,
&&表示取交集 例如
a-x&&[^b]表示a-x关于b的差集
预定义字符类 :
.任何字符(与行结束符可能匹配也可能不匹配)
\d数字:[0-9]
\D非数字: [^0-9]
\s空白字符:[ \t\n\x0B\f\r]
\S非空白字符:[^\s]
\w单词字符:[a-zA-Z_0-9]
\W非单词字符:[^\w]
POSIX 字符类,java.lang.Character 类,Unicode 块和类别的类,这些可以参见Java doc @see Pattern
边界匹配器
^行首
$行尾
\b单词边界
\B非单词边界
\A输入的开头
\G上一个匹配的结尾
\Z输入的结尾,仅用于最后的结束符(如果有的话)
\z输入的结尾
组 捕获组是从 1 开始从左到右的索引。组零表示整个模式。
简单来说组的编号可以这么看 0表示整个模式,而后指从左到右第几个左括号内就是第几组,右括号匹配即可。
Pattern类
Pattern是Java中正则表达式的抽象,这个类是final的,并且没有可用的构造函数,构造一个正则表达式Pattern使用的是工厂方法Pattern.compile(String regex)。得到Pattern对象之后可以对字符串对象进行匹配而得到结果Matcher对象,这个对象中包含了丰富的信息,比如是否匹配成功boolean matches()。
Pattern的标志构建和内嵌标志表达式
Pattern的compile方法还有个重载形式:
compile(String regex, int flags)
用于接受影响模式匹配方式的标志集。标志参数是一个位掩码,可以是下面公共静态字段中的任意一个:
标志常量名 | 等价的内嵌标志表达式 | 语义 |
---|---|---|
CANON_EQ | 启用规范等价。 | |
CASE_INSENSITIVE | (?i) | 启用不区分大小写的匹配。 |
COMMENTS | (?x) | 模式中允许空白和注释。 |
MULTILINE | (?m) | 启用多行模式。行首尾匹配对单行生效 |
DOTALL | (?s) | . 可以匹配任何字符,包括行结束符 |
LITERAL | 启用模式的字面值解析。 | |
UNICODE_CASE | (?u) | 启用 Unicode 感知的大小写折叠。 |
UNIX_LINES | (?d) | 启用 Unix 行模式。仅识别 ‘\n’ 行结束符 |
PatternSyntaxException异常
抛出未经检查的异常,表明正则表达式模式中的语法错误。通常是因为正则表达式语法有误。
Matcher类
Matcher是用某个正则表达式对某个字符串的匹配的抽象,这个类同样是final的,并且同样没有可用的构造函数,只能通过Pattern对象的matcher方法得到。Matcher可以执行3种匹配
1. 最常用的matches方法,返回是否整个字符串是否匹配。
2. lookingAt方法,从头部开始尝试匹配。
3. find方法,从没有被find匹配的第一个字符开始,这个方法可以多次匹配。
匹配的结果通过查询匹配器来获得:
group(int group) 返回在以前匹配操作期间由给定组捕获的输入子序列。
start 返回以前匹配的初始索引
start(int group) 返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引。
end 返回最后匹配字符之后的偏移量
end(int group) 返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。
简单的Java正则表达式演示
//match string Pattern p=Pattern.compile("insr"); sp(p.matcher("insr").matches()); //match with simple class p=Pattern.compile("[iard]nsr"); sp(p.matcher("insr").matches()); //match with more classes p=Pattern.compile("[a-z&&[^r-x]][\\w]{2}r\\d"); sp(p.matcher("insr3").matches()); //matches multiple p=Pattern.compile("[1258]\\d{4}(\\d)\\1{4}"); sp(p.matcher("1384522222").matches()); //match group p=Pattern.compile("(\\w{2,20})://(((www|\\w+)\\.)+(\\w{1,20})\\.([a-z]{2,3}))((/[\\w]+)*)(.*)(#[\\w]+)?(\\?[\\w]+)?"); Matcher m=p.matcher("http://hllvm.group.iteye.com/group/topic/45665#ejotj?teo=52646"); sp(m.matches()); for (int i = 0; i < m.groupCount()+1; i++) { sp(m.group(i)); }
相关文章推荐
- Java 编程下正则表达式判断字符串是否包含中文
- java正则表达式:验证字符串数字
- 黑马程序员-----JAVA 反射、正则表达式
- 在Java中用正则表达式判断一个字符串是否是数字的方法
- 黑马程序员——Java正则表达式
- 黑马程序员--JAVA<正则表达式>
- java 的正则表达式(Parrent),匹配字符串
- 黑马程序员——Java 网络通信 正则表达式
- 黑马程序员_java基础-正则表达式
- 黑马程序员—java技术blog—第七篇:正则表达式
- 利用java正则表达式来解析并获取指定的字符串
- 黑马程序员-----Java基础-----正则表达式
- 黑马程序员-Java基础总结14——正则表达式
- java中正则表达式用Pattern计算字符串的结果(四则运算);分成有括号和没括号;当然也可以采用逆波兰式
- java用正则表达式判断字符串中是否仅包含英文字母、数字和汉字
- 黑马程序员——java基础-正则表达式
- 【黑马程序员】java基础_正则表达式
- 黑马程序员——JAVA基础---正则表达式切割组的问题
- 黑马程序员-Java学习15-正则表达式
- 黑马程序员——Java基础:反射、JDK1.5新特性、正则表达式