字符串
字符串是Java中特殊的类,使用方法像一般的基本数据类型。Java没有内置的字符串类型,而是在标准Java类库中提供了一个String类来创建和操作字符串。
定义
1.直接定义
用字符串常量直接初始化一个String对象
String str = "Hello Java";
2.使用String类定义
通过String类的构造方法来创建字符串
String();// 表示一个空字符序列
String(String original);//新创建的字符串是该参数的副本
String(char[] value);//将参数中的字符数组元素全部变为字符串
String(char[] value,int offset,int count);//将参数中的字符数组元素指定位置长度的子数组变为字符串
StringBuffer,StringBuilder
StringBuffer,StringBuilder类为可变字符串类(字符串缓冲区),String被声明为final class,所有拼接字符串时候会产生很多无用的中间对象;StringBuffer为了解决大量拼接字符串时产生中间对象问题而产生,append和add方法可以将字符串添加到已有序列的末尾或指定的位置;StringBuilder为了提升性能去掉了保证线程安全的部分。
正则表达式
正则表达式(Regular Expression)在代码中常简写为regex,regexp或RE,它是计算机科学的一个概念。正则表达式时一个强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等操作,是一种可以用于模式匹配和替换的规范。一个正则表达式就是由普通的字符(如字符 a~z)以及特殊字符(元字符)组成的文字模式,它用以描述在查找文字主体时待匹配的一个或多个字符串。
创建正则表达式就是创建一个特殊的字符串
1.合法字符
字符 | 解释 |
---|---|
X | 字符x(x 可代表任何合法的字符) |
\0mnn | 八进制数 0mnn 所表示的字符 |
\xhh | 十六进制值 0xhh 所表示的字符 |
\uhhhh | 十六进制值 0xhhhh 所表示的 Unicode 字符 |
\t | 制表符(“\u0009”) |
\n | 新行(换行)符(‘\u000A’) |
\r | 回车符(‘\u000D’) |
\f | 换页符(‘\u000C’) |
\a | 报警(bell)符(‘\u0007’) |
\e | Escape 符(‘\u001B’) |
\cx | x 对应的的控制符。例如,\cM 匹配 Ctrl-M。x 值必须为 A~Z 或 a~z 之一。 |
2.特殊字符
如果匹配特殊字符,首先需要通过\
对特殊字符进行转义
特殊字符 | 说明 |
---|---|
$ | 匹配一行的结尾。要匹配 $ 字符本身,请使用\$ |
^ | 匹配一行的开头。要匹配 ^ 字符本身,请使用\^ |
() | 标记子表达式的开始和结束位置。要匹配这些字符,请使用\( 和\) |
[] | 用于确定中括号表达式的开始和结束位置。要匹配这些字符,请使用\[ 和\] |
{} | 用于标记前面子表达式的出现频度。要匹配这些字符,请使用\{ 和\} |
* | 指定前面子表达式可以出现零次或多次。要匹配 * 字符本身,请使用\* |
+ | 指定前面子表达式可以出现一次或多次。要匹配 + 字符本身,请使用\+ |
? | 指定前面子表达式可以出现零次或一次。要匹配 ?字符本身,请使用\? |
. | 匹配除换行符\n 之外的任何单字符。要匹配. 字符本身,请使用\. |
\ | 用于转义下一个字符,或指定八进制、十六进制字符。如果需匹配\ 字符,请用\\ |
| | 指定两项之间任选一项。如果要匹配丨 字符本身,请使用| |
3.预定义字符
上面的正则表达式只能匹配单个字符,需要通过预定义字符(通配符)来匹配多个字符。
预定义字符 | 说明 |
---|---|
. | 可以匹配任何字符 |
\d | 匹配 0~9 的所有数字 |
\D | 匹配非数字 |
\s | 匹配所有的空白字符,包括空格、制表符、回车符、换页符、换行符等 |
\S | 匹配所有的非空白字符 |
\w | 匹配所有的单词字符,包括 0~9 所有数字、26 个英文字母和下画线_ |
\W | 匹配所有的非单词字符 |
预定义字符记忆方法
- d 是 digit 的意思,代表数字。
- s 是 space 的意思,代表空白。
- w 是 word 的意思,代表单词。
- d、s、w 的大写形式匹配与之相反的字符
4.方括号表达式
方括号表达式几乎能匹配任何字符,如 [\u0041-\u0056] 可匹配所有中文字符
方括号表达式 | 说明 |
---|---|
表示枚举 | 例如[abc] 表示 a、b、c 其中任意一个字符;[gz] 表示 g、z 其中任意一个字符 |
表示范围:- | 例如[a-f] 表示 a~f 范围内的任意字符;[\\u0041-\\u0056] 表示十六进制字符 \u0041 到 \u0056 范围的字符。范围可以和枚举结合使用,如[a-cx-z] ,表示 ac、xz 范围内的任意字符 |
表示求否:^ | 例如[^abc] 表示非 a、b、c 的任意字符;[^a-f] 表示不是 a~f 范围内的任意字符 |
表示“与”运算:&& | 例如 [a-z&&[def]] 是 a~z 和 [def] 的交集,表示 d、e f[a-z&&^bc]] 是 a~z 范围内的所有字符,除 b 和 c 之外 [ad-z] [a-z&&[m-p]] 是 a~z 范围内的所有字符,除 m~p 范围之外的字符 |
表示“并”运算 | 并运算与前面的枚举类似。例如[a-d[m-p]] 表示 [a-dm-p] |
正则表达式还支持圆括号,用于将多个表达式组成一个子表达式,圆括号中可以使用|
。例如,正则表达式((a)|(b)|(c)
用于匹配a,b,c中的其中之一
5.边界匹配符
边界匹配符 | 说明 |
---|---|
^ | 行的开头 |
$ | 行的结尾 |
\b | 单词的边界 |
\B | 非单词的边界 |
\A | 输入的开头 |
\G | 前一个匹配的结尾 |
\Z | 输入的结尾,仅用于最后的结束符 |
\z | 输入的结尾 |
6.数量标识符
贪婪模式 | 勉强模式 | 占用模式 | 说明 |
---|---|---|---|
X? | X?? | X?+ | X表达式出现零次或一次 |
X* | X*? | X*+ | X表达式出现零次或多次 |
X+ | X+? | X++ | X表达式出现一次或多次 |
X{n} | X{n}? | X{n}+ | X表达式出现 n 次 |
X{n,} | X{n,}? | X{n,}+ | X表达式最少出现 n 次 |
X{n,m} | X{n,m}? | X{n,m}+ | X表达式最少出现 n 次,最多出现 m 次 |
- Greedy(贪婪模式):数量表示符默认采用贪婪模式,除非另有表示。贪婪模式的表达式会一直匹配下去,直到无法匹配为止。如果你发现表达式匹配的结果与预期的不符,很有可能是因为你以为表达式只会匹配前面几个字符,而实际上它是贪婪模式,所以会一直匹配下去。
- Reluctant(勉强模式):用问号后缀(?)表示,它只会匹配最少的字符。也称为最小匹配模式。
- Possessive(占有模式):用加号后缀(+)表示,目前只有 Java 支持占有模式,通常比较少用
Java正则处理
Pattern对象是正则表达式编译后在内存中的表示形式,因此正则表达式字符串必须先编译成Pattern对象,然后再利用该Pattern对象创建对应的Matcher对象,通过Matcher对象进行状态的匹配。
Pattern p = Pattern.compile("a*c");
Matcher m = p.matcher("abc");
boolean b = m.matches();
如果某个正则表达式仅需使用一次,则可以使用Pattern类的静态方法matches(),此方法自动将指定字符串编译成匿名的Pattern对象,并执行匹配。
bollean b = Pattern.matches("a*c","abc");
Pattern是不可变类,可供多个并发线程安全使用。
名称 | 说明 |
---|---|
find() | 返回目标字符串中是否包含与 Pattern 匹配的子串 |
group() | 返回上一次与 Pattern 匹配的子串 |
start() | 返回上一次与 Pattern 匹配的子串在目标字符串中的开始位置 |
end() | 返回上一次与 Pattern 匹配的子串在目标字符串中的结束位置加 1 |
lookingAt() | 返回目标字符串前面部分与 Pattern 是否匹配 |
matches() | 返回整个目标字符串与 Pattern 是否匹配 |
reset() | 将现有的 Matcher 对象应用于一个新的字符序列。 |
package com.henrik.string;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* <p>Title: Regex.java<p>
* <p>Description:通过正则表达式匹配匹配电话号码 </p>
* @author Henrik
* @date Apr 3, 2022
* @version 1.0
*/
public class Regex {
public static void main(String[] args) {
Regex regex = new Regex();
//网络爬虫
regex.reptile();
//注册匹配
regex.register();
}
@SuppressWarnings({ "resource", "unused" })
private void register() {
try {
String regex = "0\\d{2,3}[-]?\\d{7,8}|0\\d{2,3}\\s?\\d{7,8}|13[0-9]\\d{8}|15[1089]\\d{8}";
String regex2 = "13[0-9]\\\\d{8}|15[1089]\\\\d{8}";
Scanner scan = new Scanner(System.in);
Pattern pattern = Pattern.compile(regex);
String answer = "N";
do {
System.out.println("请输入你的电话号码:");
String phone = scan.next();
Matcher matcher = pattern.matcher(phone);
boolean bool = matcher.matches();
if(bool) {
System.out.println("注册成功!");
}
else {
System.out.println("格式错误,是否重新输入?(Y/N 或者 y/n)");
answer = scan.next();
}
}while(answer.equalsIgnoreCase("Y"));
System.out.println("注册失败!");
} catch (Exception e) {
e.printStackTrace();
}
}
private void reptile() {
String str = "用户1>姓名:张山,电话:13767895342,地址:花园小区;用户2>姓名:李思,电话:13523456789,地址:花园小区...";
Pattern pattern = Pattern.compile("(137|135)\\d{8}");
Matcher matcher = pattern.matcher(str);
while(matcher.find()) {
System.out.println(matcher.group());
}
}
}