2021-07-29笔记

3.正则表达式

3.1正则表达式的使用

实现相同的功能,用String、StringBuffer、StringBuilder可以实现,用正则表达式也可以实现。

但是在实现过程中, 复杂程度是完全不一样的。

3.2基本的元字符

3.2.1正则表达式的匹配规则

逐个字符进行匹配, 判断是否和正则表达式中定义的规则一致。

以下借助 String 类中的 matches 方法进行正则基础的语法讲解。

boolean matches(String regex);
是String类中的非静态方法, 使用字符串对象调用这个方法, 参数是一个正则表达式。
使用指定的正则表达式, 和当前的字符串进行匹配。 验证当前的字符串是否和指定的规
则是相匹配的。

3.2.2元字符

元字符意义
^匹配一个字符串的开头。在java的正则匹配中,可以省略不写
$匹配一个字符串的结尾。在java的正则匹配中,可以省略不写
[]匹配一位字符。 [abc]:表示这一位的字符,可以是a、也可以是b、也可以是c [abc]:表示这一位的字符,可以是a、也可以是b、也可以是c [a-z]:表示这一位的字符,可以是[a,z]范围内的任意的字符 [a-zABC]:表示这一位的字符,可以是[a,z]范围内的任意字符,或者A、 或者B、或者C [a-zA-Z]:表示这一位的字符,可以是任意的字母,包括大写字母和小写字母 [ ^abc]:表示这一位的字符,可以是除了a、b、c之外的任意字符 [ ^a-z[hk]]:表示这一位的字符,不能是任意的小写字母,但是h、k除外
\转义字符。由于正则表达式在java中需要写在一个字符串中,而字符串中的\ 也是一个转义字符。因此java中写正则表达式的时候,转义字符都是\\ 使得某些特殊字符称为普通字符,可以进行规则的指定。 使得某些普通字符变得具有特殊含义
\d匹配所有的数字,等同于[0-9]
\D匹配所有的非数字,等同于[ ^0-9]
\w匹配所有的单词字符,等同于[a-zA-Z0-9_]
\W匹配所有的非单词字符,等同于[ ^a-zA-Z0-9_]
.通配符,可以匹配任意一个字符
+前面的一位或者一组字符,连续出现了一次或多次
?前面的一位或者一组字符,连续出现了一次或零次
*前面的一位或者一组字符,连续出现了零次,一次或者多次
{}对前面的一位或者一组字符出现次数的精准匹配。 {m}:表示前面的一位或者一组字符连续出现了m次 {m,}:表示前面的一位或者一组字符连续出现了至少m次 {m,n}:表示前面的一位或者一组字符连续出现了至少m次,最多n次
|作用于整体或者一个分组,表示匹配的内容,可以是任意一个部分。 abc|123|opq:表示整体部分,可以是abc,也可以是123,也可以是opq
()分组,把某些连续的字符试为一个整体对待

3.3 String类中的常用的方法

3.3.1字符串的匹配

// QQ号的规则:
// 1. 纯数字组成的
// 2. 不能以0作为开头
// 3. 长度在 [6,11]
private static boolean chechQQ(String qqNumber) {
return qqNumber.matches("[1-9]\\d{5,10}");
}
// 验证邮箱的合法性
// 1. 126
// 2. 前半部分可以是任意的单词字符, 长度限制在 [4,12]
// 3. 以.com作为结尾
private static boolean checkEmail(String email) {
return email.matches("\\w{4,12}@126\\.com");
}

3.3.2字符串的切割

private static void split() {
// 需求: 将一个存储有所有的姓名的字符串,切割出每一个名字。
String names = "lily lucy polly Jim LiLei
HanMeimei";
// 实现: 借助字符串的一个方法 split(String regex)
// 将字符串中,满足正则规则的子部分,切割掉
String[] nameArr = names.split(" +");
System.out.println(Arrays.toString(nameArr));
}

3.3.3字符串的替换

private static void replace() {
// 需求: 将这个存储有所有的名字的字符串,名字之间的分隔用, 来替代
String names = "lily lucy polly Jim LiLei
HanMeimei";
// 实现: 借助字符串中的一个方法 replaceAll(String regex, String
replacement)
// 将字符串中,满足指定正则的部分,替换成 replacement
// String result = names.replaceAll(" +", ", ");
String result = names.replaceFirst(" +", ", ");
System.out.println(result);
}
private static void example() {
// 需求: 将一个手机号的中间4位替换成 ****
// 17788889999 => 177****9999
String phoneNumber = "17788889999";
// 在replace方法中,使用$1获取第一个分组的值
String result = phoneNumber.replaceAll("(1\\d{2})(\\d{4})(\\d{4})",
"$1****$3");
System.out.println(result);
}

3.4Pattern和Matcher类

3.4.1. 简介

在 java.util.regex 包中

Pattern类: 在Java中,正则表达式的载体。使用正则表达式进行字符串的校验、切割、替 换,都需要使用到这个类。

 在Java中,使用字符串的形式来写正则表达式。此时,如果需要这个字符串被当做是一 个正则表达式使用, 必须先由这样的字符串编译为 Pattern 类的对象。然后才可以使用 这个对象的某些方法, 进行常见的操作(校验、切割、替换)。 

Matcher类: 在Java中, 对一个正则校验的结果描述。

3.4.2常用方法

Pattern

修饰符&返回值方法描述
static booleanmatch(String regex, CharSequence sequence)静态的规则校验,直接校验某一个字符串 是否符合某一个规则
static Patterncompile(String regex)将一个字符串,编译为Pattern对象, 从而可以当做是一个正则表达式使用
String[]split(CharSequence sequence)将一个字符序列,按照指定的规则 进行切割,得到每一个切割部分
String[]split(CharSequence sequence,int limit)将一个字符序列,按照指定的规则进行 切割,切割成指定的段数,得到每一个切割部分。
Matchermatcher(CharSequence sequence)将一个正则表达式和一个字符串进行校验

Matcher

操作修饰符&返回值方法描述
booleanmatches()得到本次整体匹配的结果,一个字符串是否和 一个正则表达式是整体匹配的
booleanfind()查找字符串中,是否有满足指定规则的子部分
booleanfind(int start)查找字符串中,从指定下标开始往后,有没有 满足指定规则的子部分
Stringgroup()获取当前匹配到的字符串
intstart()获取当前比配到的部分首字符的下标
intend()获取当前匹配到的部分尾字符的下标+1
booleanlookingAt()查找字符串,是否有满足指定规则的子部分, 每次查询都从第0位开始。

find()

从字符串的第0位开始查询, 查询是否有满足指定规则的子部分。 当再次调用find()的时候, 从上次查询到的位置开始, 继续向后查询。

关于查询

无论是 matches, 还是find, 还是lookingAt, 在字符串中进行校验、匹配的时候, 是有一 个浮标存在的。

4.Lambda表达式

4.1 Lambda表达式的使⽤场景

通常来讲,使⽤lambda表达式,是为了简化接⼝实现的。

关于接⼝实现,可以有很多种⽅式来实现。例如: 设计接⼝的实现类、使⽤匿名内 部类。但是lambda表达式,⽐这两种⽅式都简单

4.2 Lambda表达式对接⼝的要求

虽然说, lambda表达式可以在⼀定程度上简化接⼝的实现。 但是, 并不是所有的 接⼝都可以使⽤lambda表达式来简洁实现的。

lambda表达式毕竟只是⼀个匿名⽅法。 当实现的接⼝中的⽅法过多或者多少的时 候, lambda表达式都是不适⽤的。

lambda表达式,只能实现函数式接⼝

4.3函数式接口

  • 基础概念

    如果说, ⼀个接⼝中, 要求实现类必须实现的抽象⽅法, 有且只有⼀个! 这样的接 ⼝, 就是函数式接⼝。

  • @FunctionalInterface

    是⼀个注解, ⽤在接⼝之前, 判断这个接⼝是否是⼀个函数式接⼝。 如果是函数式 接⼝, 没有任何问题。 如果不是函数式接⼝, 则会报错。 功能类似于 @Override

    @FunctionalInterface
    interface FunctionalInterfaceTest {
     void test();
    }
  • 系统内置的若⼲函数式接⼝(不常用,但是要注意)

4.4 Lambda表达式的语法

4.4.1. Lambda表达式的基础语法

lambda表达式,其实本质来讲,就是⼀个匿名函数。 因此在写lambda表达式的时 候,不需要关⼼⽅法名是什么。

实际上,我们在写lambda表达式的时候, 也不需要关⼼返回值类型。

我们在写lambda表达式的时候,只需要关注两部分内容即可:参数列表和⽅法体

lambda表达式的基础语法:

(参数) -> {
    ⽅法体
}

参数部分 : ⽅法的参数列表, 要求和实现的接⼝中的⽅法参数部分⼀致, 包括参数 的数量和类型。

方法体部分 : ⽅法的实现部分, 如果接⼝中定义的⽅法有返回值, 则在实现的时 候, 注意返回值的返回。

-> : 分隔参数部分和⽅法体部分。

4.5 Lambda表达式的语法进阶

在一些代码中,的确可以使⽤lambda表达式实现接⼝,但是依然不够简洁,有简化的空间。

4.5.1参数部分的精简

  • 参数的类型

    • 由于在接⼝的⽅法中,已经定义了每⼀个参数的类型是什么。 ⽽且在使⽤ lambda表达式实现接⼝的时候, 必须要保证参数的数量和类型需要和接⼝ 中的⽅法保持⼀致。 因此, 此时lambda表达式中的参数的类型可以省略不 写。

    • 注意事项:

      • 如果需要省略参数的类型,要保证:要省略,每⼀个参数的类型都必须省略不写。绝对不能出现,有的参数类型省略了,有的参数类型没有省略

// 多个参数、⽆返回值的⽅法实现
NoneReturnMutipleParameter lambda1 = (a, b) -> {
    System.out.println("多个参数、⽆返回值⽅法的实现: 参数a是
" + a + ", 参数b是 " + b);
    };
  • 参数的小括号

    • 如果⽅法的参数列表中的参数数量 有且只有⼀个 ,此时,参数列表的⼩括 号是可以省略不写的。

    • 注意事项:

      • 只有当参数的数量是⼀个的时候, 多了、少了都不能省略。

      • 省略掉⼩括号的同时, 必须要省略参数的类型

// 有参、⽆返回值的⽅法实现
NoneReturnSingleParameter lambda2 = a -> {
    System.out.println("⼀个参数、⽆返回值⽅法的实现: 参数是 "+ a);
};

4.5.2方法体部分的精简

  • 方法体⼤括号的精简

    • 当⼀个⽅法体中的逻辑, 有且只有⼀句的情况下, ⼤括号可以省略。

// 有参、⽆返回值的⽅法实现
NoneReturnSingleParameter lambda2 = a ->
System.out.println("⼀个参数、⽆返回值⽅法的实现: 参数是 " +
a);
  • return的精简

    • 如果⼀个⽅法中唯⼀的⼀条语句是⼀个返回语句, 此时在省略掉⼤括号的同 时, 也必须省略掉return。

SingleReturnMutipleParameter lambda3 = (a, b) -> a + b;

4.5.3静态方法的引用

  • 语法:

    • 类:静态⽅法

  • 注意事项:

  • 在引⽤的⽅法后⾯,不要添加⼩括号。

  • 引⽤的这个⽅法,参数(数量、类型)和 返回值,必须要跟接⼝中定义的 ⼀致。

4.5.4非静态方法的引用

  • 语法:

    • 对象::⾮静态⽅法

  • 注意事项:

    • 在引⽤的⽅法后⾯,不要添加⼩括号。

    • 引⽤的这个⽅法,参数(数量、类型)和 返回值, 必须要跟接⼝中定义的 ⼀致。

4.5.6构造方法的引用

  • 使⽤场景

    • 如果某⼀个函数式接⼝中定义的⽅法, 仅仅是为了得到⼀个类的对象。 此 时我们就可以使⽤构造⽅法的引⽤, 简化这个⽅法的实现。

  • 语法

    • 类名::new

  • 注意事项

    • 可以通过接⼝中的⽅法的参数, 区分引⽤不同的构造⽅法。

4.5.7 对象方法的特殊引用

如果在使⽤lambda表达式,实现某些接⼝的时候。lambda表达式中包含了某⼀个 对象,此时⽅法体中,直接使⽤这个对象调⽤它的某⼀个⽅法就可以完成整体的逻辑。其他的参数,可以作为调⽤⽅法的参数。 此时,可以对这种实现进⾏简化。

4.5.8 Lambda表达式需要注意的问题

这⾥类似于局部内部类、匿名内部类,依然存在闭包的问题。

如果在lambda表达式中,使⽤到了局部变量,那么这个局部变量会被隐式的声明为 final。 是⼀个常量, 不能修改值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值