1 String
1.1 String对象简介
1. 简介
- String类: 代表字符串。 Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。
- String是一个final类,代表不可变的字符序列。
- 字符串是常量,用双引号引起来表示。 它们的值在创建之后不能更改。
- String对象的字符内容是存储在一个字符数组value[]中的。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
2. 产生字符串
String str = "hello";
//本质上this.value = new char[0];
String s1 = new String();
//this.value = original.value;
String s2 = new String(String original);
//this.value = Arrays.copyOf(value, value.length);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count);
1.2 string的内存结构
情况1:
情况2:
情况3:
情况4:
1.3 字符串的拼接
- 编译期能确定值的字符串比如s1,s2, s3,存在常量池
- 编译期不能确定值的字符串比如,s4,s5,s6,存在堆里
- intern()方法:
- 返回字符串对应的常量池字符序列
- 如果常量池中没有,会把字符串存到常量池
@Test
public void test2() {
String s1 = "hello";
String s2 = "world";
String s3 = "hello" + "world";
String s4 = s1 + "world";
String s5 = s1 + s2;
String s6 = (s1 + s2).intern();
System.out.println(s3 == s4);
System.out.println(s3 == s5);
System.out.println(s4 == s5);
System.out.println(s3 == s6);
}
例2:
1.4 常用方法
- int length(): 返回字符串的长度: return value.length
- char charAt(int index): 返回某索引处的字符return value[index]
- boolean isEmpty(): 判断是否是空字符串: return value.length == 0
- String toLowerCase(): 使用默认语言环境, 将 String 中的所有字符转换为小写
- String toUpperCase(): 使用默认语言环境, 将 String 中的所有字符转换为大写
- String trim(): 返回字符串的副本, 忽略前导空白和尾部空白
- boolean equals(Object obj): 比较字符串的内容是否相同
- boolean equalsIgnoreCase(String anotherString): 与equals方法类似, 忽略大小写
- String concat(String str): 将指定字符串连接到此字符串的结尾。 等价于用“+”
- int compareTo(String anotherString): 比较两个字符串的大小
- String substring(int beginIndex): 返回一个新的字符串,
它是此字符串的从beginIndex开始截取到最后的一个子字符串。 - String substring(int beginIndex, int endIndex) : 返回一个新字符串,
它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。 - boolean contains(CharSequence s): 当且仅当此字符串包含指定的 char 值序列时,返回 true
- int indexOf(String str): 返回指定子字符串在此字符串中第一次出现处的索引
- int indexOf(String str, int fromIndex):
返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始 - int lastIndexOf(String str): 返回指定子字符串在此字符串中最右边出现处的索引
- int lastIndexOf(String str, int fromIndex):
返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索注: indexOf和lastIndexOf方法如果未找到都是返回-1 - boolean endsWith(String suffix): 测试此字符串是否以指定的后缀结束
- boolean startsWith(String prefix): 测试此字符串是否以指定的前缀开始
- boolean startsWith(String prefix, int toffset):
测试此字符串从指定索引开始的子字符串是否以指定前缀开始 - String replace(char oldChar, char newChar): 返回一个新的字符串, 它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
- String replace(CharSequence target, CharSequence replacement):
使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。 - String replaceAll(String regex, String replacement) : 使 用 给 定
的replacement 替换此字符串所有匹配给定的正则表达式的子字符串。 - String replaceFirst(String regex, String replacement) : 使 用 给 定
的replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。 - boolean matches(String regex): 告知此字符串是否匹配给定的正则表达式。
- String[] split(String regex): 根据给定正则表达式的匹配拆分此字符串。
- String[] split(String regex, int limit): 根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个, 如果超过了, 剩下的全部都放到最后一个元素中。
@Test
public void test4() {
// 定义一个字符串对象
String s = "helloworld";
// int length():获取字符串的长度。
System.out.println("s.length:" + s.length());
System.out.println("----------------------");
// char charAt(int index):获取指定索引位置的字符
System.out.println("charAt:" + s.charAt(0));
System.out.println("----------------------");
// int indexOf(int ch):返回指定字符在此字符串中第一次出现处的索引。
System.out.println("indexOf:" + s.indexOf('l'));
System.out.println("----------------------");
// int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引。
System.out.println("indexOf:" + s.indexOf("owo"));
System.out.println("----------------------");
// int indexOf(int ch,int fromIndex):返回指定字符在此字符串中从指定位置后第一次出现处的索引。
System.out.println("indexOf:" + s.indexOf('l', 4));
System.out.println("indexOf:" + s.indexOf('k', 4)); // -1
System.out.println("indexOf:" + s.indexOf('l', 40)); // -1
System.out.println("----------------------");
// 自己练习:int indexOf(String str,int
// fromIndex):返回指定字符串在此字符串中从指定位置后第一次出现处的索引。
// String substring(int start):从指定位置开始截取字符串,默认到末尾。包含start这个索引
System.out.println("substring:" + s.substring(5));
System.out.println("substring:" + s.substring(5,7)); //开始时5,结束是7,不包括7
System.out.println("substring:" + s.substring(0));
System.out.println("----------------------");
// String substring(int start,int
// end):从指定位置开始到指定位置结束截取字符串。包括start索引但是不包end索引
System.out.println("substring:" + s.substring(3, 8));
System.out.println("substring:" + s.substring(0, s.length()));
String s3 = " abc 123 ";
System.out.println(s3.trim().length()); //去掉前后两端的空格
String s4 = "a,b,c,d,e,123";
String[] s5 = s4.split(",");
for (int i = 0; i < s5.length; i++) {
System.out.println(s5[i]);
}
}
2 StringBuffer和StringBuilder
当append和insert时,如果原来value数组长度不够,可扩容。
- 如上这些方法支持方法链操作。
- 解决了string拼接的性能问题
1. 常用方法
- StringBuffer append(xxx):提供了很多的append()方法, 用于进行字符串拼接
- StringBuffer delete(int start,int end):删除指定位置的内容
- StringBuffer replace(int start, int end, String
str):把[start,end)位置替换为str - StringBuffer insert(int offset, xxx):在指定位置插入xxx
- StringBuffer reverse() :把当前字符序列逆转 public int indexOf(String str)
- public String substring(int start,int end)
- public int length()
- public char charAt(int n )
- public void setCharAt(int n ,char ch)
2. StringBuffer和StringBuilder类
-
StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列, 而且提供相关功能的方法也一样
-
面试题:对比String、 StringBuffer、 StringBuilder
-
String(JDK1.0): 不可变字符序列 final value[]
-
StringBuffer(JDK1.0): 可变字符序列、效率低、线程安全
StringBuilder(JDK 5.0):可变字符序列、效率高、 线程不安全
例;
-
@Test
public void test1() {
//hello + world + java + python
StringBuffer sb = new StringBuffer();
sb.append("hello ").append("world ").append("java ").append("python ");
System.out.println(sb.toString());
}
/**
* 1697
*/
@Test
public void test2() {
String text = "";
long t1 = System.currentTimeMillis(); //时间戳:1970.1.1.0.0.0.0到现在的毫秒数
for (int i = 0; i < 20000; i++) {
text = text + i;
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
}
@Test
public void test3() {
StringBuffer sb = new StringBuffer();
long t1 = System.currentTimeMillis(); //时间戳:1970.1.1.0.0.0.0到现在的毫秒数
for (int i = 0; i < 20000; i++) {
sb.append(i);
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
}
@Test
public void test4() {
StringBuilder sb = new StringBuilder();
long t1 = System.currentTimeMillis(); //时间戳:1970.1.1.0.0.0.0到现在的毫秒数
for (int i = 0; i < 20000; i++) {
sb.append(i);
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
}
3.日期时间类
3.1 传统日期时间处理
System.currentTimeMillis():时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数
3.1.1 Date
表示特定的瞬间,精确到毫秒,注意这个类包括上下文(时区)
-
构造器:
-
Date(): 使用无参构造器创建的对象可以获取本地当前时间。
-
Date(long date)
-
常用方法
-
getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
-
toString():把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue,Wed, Thu, Fri, Sat), zzz是时间标准。
-
其它很多方法都过时了。
-
@Test
public void test1() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
//创建时间,方式1
Date date = new Date(); //当前时间
System.out.println(sdf.format(date));
//方式2
Date date2 = new Date(100);
System.out.println(sdf.format(date2)); //注意时区 1970.1.1 8:0:0.0.100
//得到时间戳
System.out.println(date2.getTime());
System.out.println(date.getTime());
}
3.1.2 SimpleDateFormat
-
Date类的API不易于国际化,大部分被废弃了,
java.text.SimpleDateFormat类是一个不与语言环境有关的方式来格式化和解析日期的具体类。 -
它允许进行格式化:日期 -> 文本、 解析:文本 -> 日期 格式化:
- SimpleDateFormat() :默认的模式和语言环境创建对象
- public SimpleDateFormat(String pattern): 该构造方法可以用参数pattern指定的格式创建一个对象
- public String format(Date date): 方法格式化时间对象date
-
解析:
-
public Date parse(String source): 从给定字符串的开始解析文本,以生成一个日期。
@Test
public void test2() throws ParseException {
Date date1 = new Date();
System.out.println(date1);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println(sdf.format(date1));
String dateStr = "1970-01-1 08:0:0.0";
Date date2 = sdf.parse(dateStr);
//打印时间戳
System.out.println(date2.getTime());
String dateStr3 = "1970年01月1日";
SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy年MM月dd日");
Date date3 = sdf3.parse(dateStr3);
//打印时间戳
System.out.println(date3.getTime());
}
3.1.3 Calander
-
场景:
- 比如得到一个日期的5个月后的时间
- 指定的年月日,时分秒对应的时间
- 得到一个时间的年,月,日,时分秒
-
Calendar是一个抽象基类,主用用于完成日期字段之间相互操作的功能。
- 获取Calendar实例的方法
- 使用Calendar.getInstance()方法
-
调用它的子类GregorianCalendar的构造器。
-
一个Calendar的实例是系统时间的抽象表示,通过get(int field)方法来取得想要的时间信息。比如YEAR、 MONTH、DAY_OF_WEEK、 HOUR_OF_DAY 、MINUTE、 SECOND
- public void set(int field,int value)
- public void add(int field,int amount)
- public final Date getTime()
- public final void setTime(Date date)
-
注意
- 获取月份时: 一月是0,二月是1,以此类推, 12月是11
- 获取星期时: 周日是1,周一是2 , 。 。。。周六是7
@Test
public void test3() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
//产生
Calendar c = Calendar.getInstance(); //当前时间new Date()
//得到field
System.out.println(c.get(Calendar.YEAR)); //得到年
System.out.println(c.get(Calendar.MONTH)); //得到月 传统日期月从0开始,周从周日=1开始
System.out.println(c.get(Calendar.DAY_OF_MONTH));
System.out.println(c.get(Calendar.HOUR_OF_DAY));
//设置field
c.set(Calendar.MONTH, 0); //传统日期月从0开始
System.out.println(sdf.format(c.getTime()));//得到date
//减3个月
c.add(Calendar.MONTH, -3);
System.out.println(sdf.format(c.getTime()));//得到date
//创建1970-1-1 8:0:0.0时间
//方式1:
String dateStr = "1970-01-1 08:0:0.0";
//把字符串解析成日期,string->date
Date date1 = sdf.parse(dateStr);
System.out.println(date1.getTime());
//方式2
Calendar c2 = Calendar.getInstance();
c2.set(1970, 0, 1,8,0,0);
c2.set(Calendar.MILLISECOND, 0);
System.out.println(sdf.format(c2.getTime()));
//当前时间的4周后
Calendar c3 = Calendar.getInstance(); //当前时间
c3.add(Calendar.WEEK_OF_YEAR, 5);
System.out.println(sdf.format(c3.getTime()));
}
3.2 JDK8新日期API
Java 8中引入的java.time API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务。
Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API。新的 java.time 中包含了所有关于本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。历史悠久的 Date 类新增了 toInstant() 方法,用于把 Date 转换成新的表示形式。这些新增的本地化时间日期 API 大大简化了日期时间和本地化的管理。
- java.time – 包含值对象的基础包
- java.time.chrono – 提供对不同的日历系统的访问
- java.time.format – 格式化和解析时间和日期
- java.time.temporal – 包括底层框架和扩展特性
- java.time.zone – 包含时区支持的类
3.2.1 LocalDateTime
LocalDate、 LocalTime、 LocalDateTime 类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。
- LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期。
- LocalTime表示一个时间,而不是日期。
- LocalDateTime是用来表示日期和时间的, 这是一个最常用的类之一。
注: ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法,也就是公历。
3.3.2 Instant
- Instant:时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间戳。
- 在处理时间和日期的时候,我们通常会想到年,月,日,时,分,秒。然而,这只是时间的一个模型,是面向人类的。第二种通用模型是面向机器的,或者说是连续的。在此模型中,时间线中的一个点表示为一个很大的数,这有利于计算机处理。
在UNIX中,这个数从1970年开始,以秒为的单位;同样的,在Java中,也是从1970年开始,但以毫秒为单位。 - java.time包通过值类型Instant提供机器视图,不提供处理人类意义上的时间单位。
Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲, 它只是简单的表示自1970年1月1日0时0分0秒(
UTC)开始的秒数。 因为java.time包是基于纳秒计算的,所以Instant的精度可以达到纳秒级。 - (1 ns = 10-9 s) 1秒 = 1000毫秒 =106微秒=109纳秒
注意:时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数
3.2.3 DateTimeFormatter
- java.time.format.DateTimeFormatter 类:该类提供了三种格式化方法:
- 预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
- 本地化相关的格式。如: ofLocalizedDateTime(FormatStyle.LONG)
- 自定义的格式。如: ofPattern(“yyyy-MM-dd hh:mm:ss”)
3.2.4 与传统日期类转换
@Test
public void test5() throws ParseException {
//得到当前时间
//LocalDateTime:(UTC)日期时间,理解成Date + Calander
//LocalDate:日期
//LocalTime:时间
LocalDateTime l1 = LocalDateTime.now();
System.out.println("l1 = " + l1);
//得到field
System.out.println(l1.getMonth().getValue()); //新时间api,月从1开始
System.out.println(l1.getYear());
System.out.println(l1.get(ChronoField.HOUR_OF_DAY)); //时
//设置field,支持chain方法链,设置1月1日
LocalDateTime l2 = l1.withMonth(1).withDayOfMonth(1);
System.out.println(l2);
//加3个月,加3周
// l2.plusMonths(3).plus(3, ChronoUnit.WEEKS)
LocalDateTime l3 = l2.plusMonths(3).plusWeeks(3);
System.out.println(l3);
//减3月
LocalDateTime l4 = l3.minusMonths(3);
System.out.println(l4);
//创建1970-1-1 8:0:0.0时间
LocalDateTime l5 = LocalDateTime.of(1970, 1, 1, 0, 0, 0, 0);
System.out.println(l5);
//时间戳操作 Instant
Instant i1 = l5.toInstant(ZoneOffset.UTC); //得到utc时间的Instant
System.out.println(i1.toEpochMilli());
// ZoneOffset.getAvailableZoneIds().forEach(s -> System.out.println(s));
LocalDateTime l6 = LocalDateTime.of(1970, 1, 1, 8, 0, 0, 0);
Instant i2 = l6.toInstant(ZoneOffset.ofHours(8)); //得到东8区的Instant
System.out.println(i2.toEpochMilli()); //utc时间的1970.1.1.0点,北京时间的8点,是时间戳的0
//格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒.SSS");
System.out.println(formatter.format(LocalDateTime.now()));
// formatter.parse() //解析一个时间
}
4 System和Runtime类
4.1 System
-
System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
-
由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的,
所以也可以很方便的进行调用。 -
成员变量
- System类内部包含in、 out和err三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。
-
成员方法
-
native long
currentTimeMillis():该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。 -
void exit(int status):该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表异常退出。
使用该方法可以在图形界面编程中实现程序的退出功能等。 -
void gc():该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。
-
String getProperty(String
key):该方法的作用是获得系统中属性名为key的属性对应的值。系统中常见的属性名以及属性的作用如下表所示:
-
public class SystemDemo1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in); //得到用户控制台输入
System.out.println("请输入i,输入0退出");
int i = in.nextInt();
if (i == 0) {
System.exit(0);
}
System.out.println("i=" + i);
}
@Test
public void test1() {
Scanner in = new Scanner(System.in); //得到用户控制台输入
System.out.println("请输入i,输入0退出");
int i = in.nextInt();
if (i == 0) {
System.exit(0);
}
System.out.println("i=" + i);
}
@Test
public void test2() {
System.out.println(System.currentTimeMillis());
}
@Test
public void test3() {
String javaVersion = System.getProperty("java.version");
System.out.println("java的version:" + javaVersion);
String javaHome = System.getProperty("java.home");
System.out.println("java的home:" + javaHome);
String osName = System.getProperty("os.name");
System.out.println("os的name:" + osName);
String osVersion = System.getProperty("os.version");
System.out.println("os的version:" + osVersion);
String userName = System.getProperty("user.name");
System.out.println("user的name:" + userName);
String userHome = System.getProperty("user.home");
System.out.println("user的home:" + userHome);
String userDir = System.getProperty("user.dir");
System.out.println("user的dir:" + userDir);
}
}
4.2 Runtime类
public void addShutdownHook(Thread hook):捕获jvm退出时间
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("捕获了jvm退出--释放资源");
}
}));
System.out.println("abc");
System.out.println("123");
System.out.println("abc");
System.out.println("123");
// int i = 1 / 0;
System.out.println("abc");
System.out.println("123");
System.out.println("abc");
System.out.println("123");
System.out.println("abc");
System.out.println("-------------------");
}
5 BigInteger和BigDecimal
5.1 BigInteger
- Integer类作为int的包装类,能存储的最大整型值为231-1, Long类也是有限的,最大为263-1。
如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。 - java.math包的BigInteger可以表示不可变的任意精度的整数。 BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供java.lang.Math 的所有相关方法。另外, BigInteger 还提供以下运算:模算术、 GCD 计算、质数测试、素数生成、位操作以及一些其他操作。
- 构造器 BigInteger(String val): 根据字符串构建BigInteger对象
- 常用方法
- public BigInteger abs():返回此 BigInteger 的绝对值的 BigInteger。
- BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger
- BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger
- BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger
- BigInteger divide(BigInteger val) :返回其值为 (this / val) 的
BigInteger。整数相除只保留整数部分。 - BigInteger remainder(BigInteger val) :返回其值为 (this % val) 的
BigInteger。 - BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val)
后跟(this % val) 的两个 BigInteger 的数组。 - BigInteger pow(int exponent) :返回其值为 (thisexponent) 的 BigInteger。
5.2 BigDecimal
-
一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中,要求数字精度比较高,故用到java.math.BigDecimal类。
-
BigDecimal类支持不可变的、任意精度的有符号十进制定点数。
-
构造器
- public BigDecimal(double val)
- public BigDecimal(String val)
-
常用方法
-
public BigDecimal add(BigDecimal augend)
-
public BigDecimal subtract(BigDecimal subtrahend)
-
public BigDecimal multiply(BigDecimal multiplicand)
-
public BigDecimal divide(BigDecimal divisor, int scale, int
roundingMode)
-
public class BigIntegerDemo {
@Test
public void test1() {
System.out.println(Integer.MAX_VALUE);
Integer i1 = 2147483647;
// Integer i2 = 2147483648;
BigInteger i3= new BigInteger("10");
System.out.println(i3);
BigInteger i4 = new BigInteger("15");
BigInteger i5 = i3.add(i4);
System.out.println(i5);
BigInteger[] arrs = i3.divideAndRemainder(new BigInteger("3"));
System.out.println(Arrays.toString(arrs));
}
}
6 正则表达式
正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"),是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。
简单来说,正则表达式就是一个很牛逼的字符串处理工具。
正则在线工具 : https://c.runoob.com/front-end/854/?optionGlobl=global
6.1 String类中的正则表达式
public class StringRegexDemo1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (true) {
System.out.println("请输入qq");
String s1 = in.nextLine();
//匹配s1中是否是6-12位数字
System.out.println(s1.matches("^[0-9]{6,12}$"));
}
}
@Test
public void test1() {
String s = "Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统";
// s = s.replaceAll("[a-zA-Z]{1,}", "hello");
s = s.replaceAll("[a-zA-Z]+", "hello");
s = s.replaceAll("\\d+", "world");
System.out.println(s);
}
@Test
public void test2() {
String s1 = "aaa,bbb,123,456,hello,word";
String[] arrs = s1.split(",");
for (int i = 0; i < arrs.length; i++) {
System.out.println(arrs[i]);
}
}
@Test
public void test3() {
String s2 = "hello12333world4567welcome34to4beijing";
String[] arrs2 = s2.split("\\d+");
for (int i = 0; i < arrs2.length; i++) {
System.out.println(arrs2[i]);
}
}
}
6.2 正则表达式常用类
6.2.1 Pattern类
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
- compile():通过正则得到一个Pattern
- matchers():方便正则表达式只是用一次,进行匹配
- matcher():产生Matcher对象,多次正则匹配推荐使用
6.2.2 Matcher类
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
1. 索引方法
索引方法提供了有用的索引值,精确表明输入字符串中在哪能找到匹配:
- public int start()返回以前匹配的初始索引。
- public int start(int group) 返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引
- public int end()返回最后匹配字符之后的偏移量。
- public int end(int group)返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。
2. 查找方法:
查找方法用来检查输入字符串并返回一个布尔值,表示是否找到该模式:
-
public boolean lookingAt() 尝试将从区域开头开始的输入序列与该模式匹配。
-
public boolean find()尝试查找与该模式匹配的输入序列的下一个子序列。
-
public boolean find(int start)重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
-
public boolean matches()尝试将整个区域与模式匹配。
-
group()返回上一个匹配项匹配的输入子序列。
-
group(int group)返回上一个匹配操作期间给定组捕获的输入子序列。
3. 替换方法
替换方法是替换输入字符串里文本的方法:
-
public Matcher appendReplacement(StringBuffer sb, String
replacement)实现非终端添加和替换步骤。 -
public StringBuffer appendTail(StringBuffer sb)实现终端添加和替换步骤。
-
public String replaceAll(String
replacement)替换模式与给定替换字符串相匹配的输入序列的每个子序列。 -
public String replaceFirst(String replacement)
替换模式与给定替换字符串匹配的输入序列的第一个子序列。 -
public static String quoteReplacement(String
s)返回指定字符串的字面替换字符串。这个方法返回一个字符串,就像传递给Matcher类的appendReplacement 方法一个字面字符串一样工作。
public class RegexDemo1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
//
Pattern pattern = Pattern.compile("^[0-9]{5,12}$"); //正则的编译对象
while (true) {
System.out.println("请输入qq");
String s1 = in.nextLine();
Matcher matcher = pattern.matcher(s1);
System.out.println(matcher.matches()); //全部匹配
// System.out.println(s1.matches("^[0-9]{5,12}$"));
}
}
@Test
public void test1() {
//正则编译对象,只匹配一次可以使用matches方法
System.out.println(Pattern.matches("^[0-9]{5,12}$", "77546313")); //正则是否全部匹配
System.out.println(Pattern.matches("^[0-9]{5,12}$", "123456")); //正则是否全部匹配
System.out.println(Pattern.matches("^[0-9]{5,12}$", "333333")); //正则是否全部匹配
Pattern pattern = Pattern.compile("^[0-9]{5,12}$");
pattern.matcher("77546313").matches();
pattern.matcher("123456").matches();
pattern.matcher("333333").matches();
}
@Test
public void test2() {
//全部匹配
Pattern pattern = Pattern.compile("\\d{5,12}");
Matcher matcher = pattern.matcher("12345a34343434");
System.out.println(matcher.matches()); //全部匹配
}
@Test
public void test3() {
//全部匹配
Pattern pattern = Pattern.compile("\\d{5,12}");
Matcher matcher = pattern.matcher("12345a34343434abc9878989");
while (matcher.find()) {//查找匹配,如果匹配返回ture
String target = matcher.group();//得到上一次匹配的子序列
System.out.println(target + "-" + matcher.start() + "-" + matcher.end()); //start得到上一个匹配的索引开始
}
}
@Test
public void test4() {
String content =
"Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。\n"
+ "Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统。\n"
+ "本教程通过简单的实例将让大家更好的了解 Java 编程语言。\n"
+ "移动操作系统 Android 大部分的代码采用 Java 编程语言编程。";
Pattern pattern = Pattern.compile("([a-zA-Z]+) | (\\d+)");
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
String target = matcher.group(2); //0:全部的正则捕获组,1:的一个小括号的正则补货组
System.out.println(target);
}
}
@Test
public void test6() {
String content =
"Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。\n"
+ "Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统。\n"
+ "本教程通过简单的实例将让大家更好的了解 Java 编程语言。\n"
+ "移动操作系统 Android 大部分的代码采用 Java 编程语言编程。";
//创建一个Pattern对象
Pattern pattern = Pattern.compile("Java");
//创建一个匹配对象
Matcher matcher = pattern.matcher(content);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
//将Java替换为java后,将最后匹配到之前的子串都添加到sb对象中
matcher.appendReplacement(sb, "java");
System.out.println("sb:" + sb);
System.out.println("---------分割线-----------");
}
//将最后匹配到的子串添加到sb中
matcher.appendTail(sb);
System.out.println("sb: " + sb);
}
}
6.3 正则表达式的语法
6.3.1 正则转义符
元符号-转义号\
\符号说明:在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义字符,否则检测不到结果,甚至会报错。
需要用到转义符的字符有:. * + ( )$ / \ ? [ ] ^ { }
注意:在Java的正则表达式中,两个\代表其他语言中的一个\
6.3.2 正则表达式支持字符
正则表达式所支持的合法字符
正则表达式中的特殊字符
预定义字符
方括号表达式
方括号表达式 说明 表示枚举 例如 [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、ef[a-z&&^bc]]是 a~z 范围内的所有字符,除 b 和 c 之外[ad-z] [a-z&&[m-p]]是 a~z 范围内的所有字符,除 m~p 范围之外的字符 表示“并”运算 并运算与前面的枚举类似。例如 [a-d[m-p]]表示 [a-dm-p]
补充:
Java正则表达式默认是区分字母大小写的,如要实现不区分大小写
(?i)abc表示abc都不区分大小写
a(?i)bc表示bc不区分大小写
a((?i)b)c表示只有b不区分大小写
Pattern pattern=Pattern.compile(regStr,Pattern.CASE_INSENSITIVE);
//当创建Pattern对象时,指定Pattern.CASE_INSENSITIVE,表示匹配不区分字母大小写
细节:Java匹配默认贪婪匹配,即尽可能匹配多的,比如"a{3,4}“,表示匹配aaa或者aaaa,但是优先匹配aaaa,例如原字符串中包括"aaaaaa”,匹配"a{3,4}“时,会找到"aaaa”
6.3.3 捕获组(capture group)
从正则表达式左侧开始,每出现一个左括号"("记做一个分组,分组编号从 1 开始。0 代表整个表达式。常用分组构造形式(pattern)
对于时间字符串:2017-04-25,表达式如下
(\d{4})-((\d{2})-(\d{2}))
有 4 个左括号,所以有 4 个分组:
6.4 正则表达式的常见应用
- 验证字符串是否全是汉字
Pattern pattern=Pattern.compile(“1+$”); - 验证字符串是否是邮编
Pattern pattern=Pattern.compile(“^\d{6}$”); - 验证字符串是否是QQ号码
Pattern pattern=Pattern.compile(“2d{4,9}$”); - 验证字符串是否是手机号码(要求:必须以13,14,15,18开头的11位数)
Pattern pattern=Pattern.compile(“^1[3|4|5|8]\d{9}$”); - 验证字符串是否是url
Pattern pattern=Pattern.compile(“^((http|https)😕/)([\w-]+\.)+[\w-]+(\/[\w-?=&/%.#]*)?$”);