1.Lambda表达式

接下来,我们学习一个JDK8新增的一种语法形式,叫做Lambda表达式。作用:用于简化匿名内部类代码的书写。

1.1 Lambda表达式基本使用

怎么去简化呢?Lamdba是有特有的格式的,按照下面的格式来编写Lamdba。

(被重写方法的形参列表) -> {
被重写方法的方法体代码;
}

需要给说明一下的是,在使用Lambda表达式之前,必须先有一个接口,而且接口中只能有一个抽象方法。(注意:不能是抽象类,只能是接口)

像这样的接口,我们称之为函数式接口,只有基于函数式接口的匿名内部类才能被Lambda表达式简化。

public interface Swimming{
void swim();
}

有了以上的Swimming接口之后,接下来才能再演示,使用Lambda表达式,简化匿名内部类书写。

public class LambdaTest1 {
public static void main(String[] args) {
// 目标:认识Lambda表达式.
//1.创建一个Swimming接口的匿名内部类对象
Swimming s = new Swimming(){
@Override
public void swim() {
System.out.println("学生快乐的游泳~~~~");
}
};
s.swim(); //2.使用Lambda表达式对Swimming接口的匿名内部类进行简化
Swimming s1 = () -> {
System.out.println("学生快乐的游泳~~~~");
};
s1.swim();
}
}

好的,我们现在已经知道Lamdba表达式可以简化基于函数式接口的匿名内部类的书写。接下来,我们可以把刚才使用Arrays方法时的代码,使用Lambda表达式简化一下了。

public class LambdaTest2 {
public static void main(String[] args) {
// 目标:使用Lambda简化函数式接口。
double[] prices = {99.8, 128, 100};
//1.把所有元素*0.8: 先用匿名内部类写法
Arrays.setAll(prices, new IntToDoubleFunction() {
@Override
public double applyAsDouble(int value) {
// value = 0 1 2
return prices[value] * 0.8;
}
});
//2.把所有元素*0.8: 改用Lamdba表达式写法
Arrays.setAll(prices, (int value) -> {
return prices[value] * 0.8;
}); System.out.println(Arrays.toString(prices));
System.out.println("-----------------------------------------------"); Student[] students = new Student[4];
students[0] = new Student("蜘蛛精", 169.5, 23);
students[1] = new Student("紫霞", 163.8, 26);
students[2] = new Student("紫霞", 163.8, 26);
students[3] = new Student("至尊宝", 167.5, 24);
//3.对数组中的元素按照年龄升序排列: 先用匿名内部类写法
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
}
});
//4.对数组中的元素按照年龄升序排列: 改用Lambda写法
Arrays.sort(students, (Student o1, Student o2) -> {
return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
});
System.out.println(Arrays.toString(students));
}
}

好的,各位同学,恭喜大家!到这里,你已经学会了Lambda表达式的基本使用了。

1.2 Lambda表达式省略规则

刚才我们学习了Lambda表达式的基本使用。Java觉得代码还不够简单,于是还提供了Lamdba表达式的几种简化写法。具体的简化规则如下

1.Lambda的标准格式
(参数类型1 参数名1, 参数类型2 参数名2)->{
...方法体的代码...
return 返回值;
} 2.在标准格式的基础上()中的参数类型可以直接省略
(参数名1, 参数名2)->{
...方法体的代码...
return 返回值;
} 3.如果{}总的语句只有一条语句,则{}可以省略、return关键字、以及最后的“;”都可以省略
(参数名1, 参数名2)-> 结果 4.如果()里面只有一个参数,则()可以省略
(参数名)->结果

接下来从匿名内部类开始、到Lambda标准格式、再到Lambda简化格式,一步一步来简化一下。同学们体会一下简化的过程。

public class LambdaTest2 {
public static void main(String[] args) {
// 目标:使用Lambda简化函数式接口。
double[] prices = {99.8, 128, 100};
//1.对数组中的每一个元素*0.8: 匿名内部类写法
Arrays.setAll(prices, new IntToDoubleFunction() {
@Override
public double applyAsDouble(int value) {
// value = 0 1 2
return prices[value] * 0.8;
}
});
//2.需求:对数组中的每一个元素*0.8,使用Lambda表达式标准写法
Arrays.setAll(prices, (int value) -> {
return prices[value] * 0.8;
});
//3.使用Lambda表达式简化格式1——省略参数类型
Arrays.setAll(prices, (value) -> {
return prices[value] * 0.8;
});
//4.使用Lambda表达式简化格式2——省略()
Arrays.setAll(prices, value -> {
return prices[value] * 0.8;
});
//5.使用Lambda表达式简化格式3——省略{}
Arrays.setAll(prices, value -> prices[value] * 0.8 ); System.out.println(Arrays.toString(prices)); System.out.println("------------------------------------ Student[] students = new Student[4];
students[0] = new Student("蜘蛛精", 169.5, 23);
students[1] = new Student("紫霞", 163.8, 26);
students[2] = new Student("紫霞", 163.8, 26);
students[3] = new Student("至尊宝", 167.5, 24); //1.使用匿名内部类
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
}
});
//2.使用Lambda表达式表达式——标准格式
Arrays.sort(students, (Student o1, Student o2) -> {
return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
});
//3.使用Lambda表达式表达式——省略参数类型
Arrays.sort(students, ( o1, o2) -> {
return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
});
//4.使用Lambda表达式表达式——省略{}
Arrays.sort(students, ( o1, o2) -> Double.compare(o1.getHeight(), o2.getHeight())); System.out.println(Arrays.toString(students));
}
}

到这里,恭喜你,对Lamdba表达式的所有写法,就学习完毕了。

2.JDK8新特性(方法引用)

各位小伙伴,接下来我们学习JDK8的另一个新特性,叫做方法引用。我们知道Lambda是用来简化匿名代码的书写格式的,而方法引用是用来进一步简化Lambda表达式的,它简化的更加过分。

到这里有小伙伴可能就想慰问Java爸爸了:“之前的代码挺好的呀!好不容易学会,你又来搞这些,把我都搞晕了。“ 说句大实话,确实有这样的问题,学习新的东西肯定会增加我们的学习成本,从心理上来说多少是有写抗拒的。但是从另一个角度想,一旦我们学会了,会大大简化我们的代码书写,提高我们编写代码的效率,而且这些新的语法都是有前提条件的,遇到的时候就简化得了。再退一步想,就算你没有学会,还是用以前的办法一点问题也没有。

给大家交代清楚了,学习方法引用可能存在的一些心理特点之后,接下来我们再正式学习方法引用的代码怎么编写。

2.1 静态方法引用

我们先学习静态方法的引用,还是用之前Arrays代码来做演示。现在准备好下面的代码

public class Test1 {
public static void main(String[] args) {
Student[] students = new Student[4];
students[0] = new Student("蜘蛛精", 169.5, 23);
students[1] = new Student("紫霞", 163.8, 26);
students[2] = new Student("紫霞", 163.8, 26);
students[3] = new Student("至尊宝", 167.5, 24); // 原始写法:对数组中的学生对象,按照年龄升序排序
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge(); // 按照年龄升序排序
}
}); // 使用Lambda简化后的形式
Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());
}
}

现在,我想要把下图中Lambda表达式的方法体,用一个静态方法代替

准备另外一个类CompareByData类,用于封装Lambda表达式的方法体代码;

public class CompareByData {
public static int compareByAge(Student o1, Student o2){
return o1.getAge() - o2.getAge(); // 升序排序的规则
}
}

现在我们就可以把Lambda表达式的方法体代码,改为下面的样子

Arrays.sort(students, (o1, o2) -> CompareByData.compareByAge(o1, o2));

Java为了简化上面Lambda表达式的写法,利用方法引用可以改进为下面的样子。**实际上就是用类名调用方法,但是把参数给省略了。**这就是静态方法引用

//静态方法引用:类名::方法名
Arrays.sort(students, CompareByData::compareByAge);

2.2 实例方法引用

还是基于上面的案例,我们现在来学习一下实例方法的引用。现在,我想要把下图中Lambda表达式的方法体,用一个实例方法代替。
在CompareByData类中,再添加一个实例方法,用于封装Lambda表达式的方法体
接下来,我们把Lambda表达式的方法体,改用对象调用方法

CompareByData compare = new CompareByData();
Arrays.sort(students, (o1, o2) -> compare.compareByAgeDesc(o1, o2)); // 降序

最后,再将Lambda表达式的方法体,直接改成方法引用写法。实际上就是用类名调用方法,但是省略的参数。这就是实例方法引用

CompareByData compare = new CompareByData();
Arrays.sort(students, compare::compareByAgeDesc); // 降序

给小伙伴的寄语:一定要按照老师写的步骤,一步一步来做,你一定能学会的!!!

2.3 特定类型的方法引用

各位小伙伴,我们继续学习特定类型的方法引用。在学习之前还是需要给大家说明一下,这种特定类型的方法引用是没有什么道理的,只是语法的一种约定,遇到这种场景,就可以这样用。

Java约定:
如果某个Lambda表达式里只是调用一个实例方法,并且前面参数列表中的第一个参数作为方法的主调, 后面的所有参数都是作为该实例方法的入参时,则就可以使用特定类型的方法引用。
格式:
类型::方法名
public class Test2 {
public static void main(String[] args) {
String[] names = {"boby", "angela", "Andy" ,"dlei", "caocao", "Babo", "jack", "Cici"}; // 要求忽略首字符大小写进行排序。
Arrays.sort(names, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
// 制定比较规则。o1 = "Andy" o2 = "angela"
return o1.compareToIgnoreCase(o2);
}
}); //lambda表达式写法
Arrays.sort(names, ( o1, o2) -> o1.compareToIgnoreCase(o2) );
//特定类型的方法引用!
Arrays.sort(names, String::compareToIgnoreCase); System.out.println(Arrays.toString(names));
}
}

3.4 构造器引用

各位小伙伴,我们学习最后一种方法引用的形式,叫做构造器引用。还是先说明一下,构造器引用在实际开发中应用的并不多,目前还没有找到构造器的应用场景。所以大家在学习的时候,也只是关注语法就可以了。

现在,我们准备一个JavaBean类,Car类

public class Car {
private String name;
private double price; public Car() { } public Car(String name, double price) {
this.name = name;
this.price = price;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public double getPrice() {
return price;
} public void setPrice(double price) {
this.price = price;
} @Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}

因为方法引用是基于Lamdba表达式简化的,所以也要按照Lamdba表达式的使用前提来用,需要一个函数式接口,接口中代码的返回值类型是Car类型

interface CreateCar{
Car create(String name, double price);
}

最后,再准备一个测试类,在测试类中创建CreateCar接口的实现类对象,先用匿名内部类创建、再用Lambda表达式创建,最后改用方法引用创建。同学们只关注格式就可以,不要去想为什么(语法就是这么设计的)。

public class Test3 {
public static void main(String[] args) {
// 1、创建这个接口的匿名内部类对象。
CreateCar cc1 = new CreateCar(){
@Override
public Car create(String name, double price) {
return new Car(name, price);
}
};
//2、使用匿名内部类改进
CreateCar cc2 = (name, price) -> new Car(name, price); //3、使用方法引用改进:构造器引用
CreateCar cc3 = Car::new; //注意:以上是创建CreateCar接口实现类对象的几种形式而已,语法一步一步简化。 //4、对象调用方法
Car car = cc3.create("奔驰", 49.9);
System.out.println(car);
}
}

3.常见算法

3.1 认识算法

接下来,我们认识一下什么是算法。算法其实是解决某个实际问题的过程和方法。比如百度地图给你规划路径,计算最优路径的过程就需要用到算法。再比如你在抖音上刷视频时,它会根据你的喜好给你推荐你喜欢看的视频,这里也需要用到算法。

我们为什么要学习算法呢?主要目的是训练我们的编程思维,还有就是面试的时候,面试官也喜欢问一下算法的问题来考察你的技术水平。最后一点,学习算法是成为一个高级程序员的必经之路。

当然我们现在并不会学习非常复杂的算法,万丈高楼平地起,我们现在只需要学习几种常见的基础算法就可以了。而且Java语言本身就内置了一些基础算法给我们使用,实际上自己也不会去写这些算法。

3.2 冒泡排序

接下来,我们学习一种算法叫排序算法,它可以价格无序的整数,排列成从小到大的形式(升序),或者从大到小的形式(降序)

排序算法有很多种,我们这里只学习比较简单的两种,一种是冒泡排序,一种是选择排序。学习算法我们先要搞清楚算法的流程,然后再去“推敲“如何写代码。(注意,我这里用的次是推敲,也就是说算法这样的代码并不是一次成型的,是需要反复修改才能写好的)。

先来学习冒泡排序,先来介绍一下,冒泡排序的流程

冒泡排序核心思路:每次将相邻的两个元素继续比较
如下图所示:
第一轮比较 3次
第二轮比较 2次
第三轮比较 1次
public class Test1 {
public static void main(String[] args) {
// 1、准备一个数组
int[] arr = {5, 2, 3, 1}; // 2、定义一个循环控制排几轮
for (int i = 0; i < arr.length - 1; i++) {
// i = 0 1 2 【5, 2, 3, 1】 次数
// i = 0 第一轮 0 1 2 3
// i = 1 第二轮 0 1 2
// i = 2 第三轮 0 1 // 3、定义一个循环控制每轮比较几次。
for (int j = 0; j < arr.length - i - 1; j++) {
// 判断当前位置的元素值,是否大于后一个位置处的元素值,如果大则交换。
if(arr[j] > arr[j+1]){
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}

3.3 选择排序

刚才我们学习了冒泡排序,接下来我们学习了另一种排序方法,叫做选择排序。按照我们刚才给大家介绍的算法的学习方式。先要搞清楚算法的流程,再去推敲代码怎么写。

所以我们先分析选择排序算法的流程:选择排序的核心思路是,每一轮选定一个固定的元素,和其他的每一个元素进行比较;经过几轮比较之后,每一个元素都能比较到了。
接下来,按照选择排序的流程编写代码

ublic class Test2 {
public static void main(String[] args) {
// 1、准备好一个数组
int[] arr = {5, 1, 3, 2};
// 0 1 2 3 // 2、控制选择几轮
for (int i = 0; i < arr.length - 1; i++) {
// i = 0 第一轮 j = 1 2 3
// i = 1 第二轮 j = 2 3
// i = 2 第三轮 j = 3
// 3、控制每轮选择几次。
for (int j = i + 1; j < arr.length; j++) {
// 判断当前位置是否大于后面位置处的元素值,若大于则交换。
if(arr[i] > arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}

3.4查找算法

接下来,我们学习一个查找算法叫做二分查找。在学习二分查找之前,我们先来说一下基本查找,从基本查找的弊端,我们再引入二分查找,这样我们的学习也会更加丝滑一下。

**先聊一聊基本查找:**假设我们要查找的元素是81,如果是基本查找的话,只能从0索引开始一个一个往后找,但是如果元素比较多,你要查找的元素比较靠后的话,这样查找的此处就比较多。性能比较差。

再讲二分查找:二分查找的主要特点是,每次查找能排除一般元素,这样效率明显提高。但是二分查找要求比较苛刻,它要求元素必须是有序的,否则不能进行二分查找。

  • 二分查找的核心思路
第1步:先定义两个变量,分别记录开始索引(left)和结束索引(right)
第2步:计算中间位置的索引,mid = (left+right)/2;
第3步:每次查找中间mid位置的元素,和目标元素key进行比较
如果中间位置元素比目标元素小,那就说明mid前面的元素都比目标元素小
此时:left = mid+1
如果中间位置元素比目标元素大,那说明mid后面的元素都比目标元素大
此时:right = mid-1
如果中间位置元素和目标元素相等,那说明mid就是我们要找的位置
此时:把mid返回
注意:一搬查找一次肯定是不够的,所以需要把第1步和第2步循环来做,只到left>end就结束,如果最后还没有找到目标元素,就返回-1.
/**
* 目标:掌握二分查找算法。
*/
public class Test3 {
public static void main(String[] args) {
// 1、准备好一个数组。
int[] arr = {7, 23, 79, 81, 103, 127, 131, 147}; System.out.println(binarySearch(arr, 150)); System.out.println(Arrays.binarySearch(arr, 81));
} public static int binarySearch(int[] arr, int data){
// 1、定义两个变量,一个站在左边位置,一个站在右边位置
int left = 0;
int right = arr.length - 1; // 2、定义一个循环控制折半。
while (left <= right){
// 3、每次折半,都算出中间位置处的索引
int middle = (left + right) / 2;
// 4、判断当前要找的元素值,与中间位置处的元素值的大小情况。
if(data < arr[middle]){
// 往左边找,截止位置(右边位置) = 中间位置 - 1
right = middle - 1;
}else if(data > arr[middle]){
// 往右边找,起始位置(左边位置) = 中间位置 + 1
left = middle + 1;
}else {
// 中间位置处的元素值,正好等于我们要找的元素值
return middle;
}
}
return -1; // -1特殊结果,就代表没有找到数据!数组中不存在该数据!
}
}

4.正则表达式

接下来,我们学习一个全新的知识,叫做正则表达式。正则表达式其实是由一些特殊的符号组成的,它代表的是某种规则。

正则表达式的作用1:用来校验字符串数据是否合法

正则表达式的作用2:可以从一段文本中查找满足要求的内容

4.1 正则表达式初体验

现在,我们就以QQ号码为例,来体验一下正则表达式的用法。注意:现在仅仅只是体验而已,我们还没有讲正则表达式的具体写法。

  • 不使用正则表达式,校验QQ号码代码是这样的
public static boolean checkQQ(String qq){
// 1、判断qq号码是否为null
if(qq == null || qq.startsWith("0") || qq.length() < 6 || qq.length() > 20){
return false;
} // 2、qq至少是不是null,不是以0开头的,满足6-20之间的长度。
// 判断qq号码中是否都是数字。
// qq = 2514ghd234
for (int i = 0; i < qq.length(); i++) {
// 根据索引提取当前位置处的字符。
char ch = qq.charAt(i);
// 判断ch记住的字符,如果不是数字,qq号码不合法。
if(ch < '0' || ch > '9'){
return false;
}
}
// 3、说明qq号码肯定是合法
return true;
}
  • 用正则表达式代码是这样的
public static boolean checkQQ1(String qq){
return qq != null && qq.matches("[1-9]\\d{5,19}");
}

我们发现,使用正则表达式,大大简化的了代码的写法。这个代码现在不用写,体验到正则表达式的优势就可以了。

4.2 正则表达式书写规则

前面我们已经体验到了正则表达式,可以简化校验数据的代码书写。这里需要用到一个方法叫matches(String regex)。这个方法时属于String类的方法。

这个方法是用来匹配一个字符串是否匹配正则表达式的规则,参数需要调用者传递一个正则表达式。但是正则表达式不能乱写,是有特定的规则的。

下面我们就学习一下,正则表达式的规则。从哪里学呢?在API中有一个类叫做Pattern,我们可以到API文档中搜索,关于正则表达式的规则,这个类都告诉我们了。我这里把常用的已经给大家整理好了。

我们将这些规则,在代码中演示一下

/**
* 目标:掌握正则表达式的书写规则
*/
public class RegexTest2 {
public static void main(String[] args) {
// 1、字符类(只能匹配单个字符)
System.out.println("a".matches("[abc]")); // [abc]只能匹配a、b、c
System.out.println("e".matches("[abcd]")); // false System.out.println("d".matches("[^abc]")); // [^abc] 不能是abc
System.out.println("a".matches("[^abc]")); // false System.out.println("b".matches("[a-zA-Z]")); // [a-zA-Z] 只能是a-z A-Z的字符
System.out.println("2".matches("[a-zA-Z]")); // false System.out.println("k".matches("[a-z&&[^bc]]")); // : a到z,除了b和c
System.out.println("b".matches("[a-z&&[^bc]]")); // false System.out.println("ab".matches("[a-zA-Z0-9]")); // false 注意:以上带 [内容] 的规则都只能用于匹配单个字符 // 2、预定义字符(只能匹配单个字符) . \d \D \s \S \w \W
System.out.println("徐".matches(".")); // .可以匹配任意字符
System.out.println("徐徐".matches(".")); // false // \转义
System.out.println("\"");
// \n \t
System.out.println("3".matches("\\d")); // \d: 0-9
System.out.println("a".matches("\\d")); //false System.out.println(" ".matches("\\s")); // \s: 代表一个空白字符
System.out.println("a".matches("\s")); // false System.out.println("a".matches("\\S")); // \S: 代表一个非空白字符
System.out.println(" ".matches("\\S")); // false System.out.println("a".matches("\\w")); // \w: [a-zA-Z_0-9]
System.out.println("_".matches("\\w")); // true
System.out.println("徐".matches("\\w")); // false System.out.println("徐".matches("\\W")); // [^\w]不能是a-zA-Z_0-9
System.out.println("a".matches("\\W")); // false System.out.println("23232".matches("\\d")); // false 注意:以上预定义字符都只能匹配单个字符。 // 3、数量词: ? * + {n} {n, } {n, m}
System.out.println("a".matches("\\w?")); // ? 代表0次或1次
System.out.println("".matches("\\w?")); // true
System.out.println("abc".matches("\\w?")); // false System.out.println("abc12".matches("\\w*")); // * 代表0次或多次
System.out.println("".matches("\\w*")); // true
System.out.println("abc12张".matches("\\w*")); // false System.out.println("abc12".matches("\\w+")); // + 代表1次或多次
System.out.println("".matches("\\w+")); // false
System.out.println("abc12张".matches("\\w+")); // false System.out.println("a3c".matches("\\w{3}")); // {3} 代表要正好是n次
System.out.println("abcd".matches("\\w{3}")); // false
System.out.println("abcd".matches("\\w{3,}")); // {3,} 代表是>=3次
System.out.println("ab".matches("\\w{3,}")); // false
System.out.println("abcde徐".matches("\\w{3,}")); // false
System.out.println("abc232d".matches("\\w{3,9}")); // {3, 9} 代表是 大于等于3次,小于等于9次 // 4、其他几个常用的符号:(?i)忽略大小写 、 或:| 、 分组:()
System.out.println("abc".matches("(?i)abc")); // true
System.out.println("ABC".matches("(?i)abc")); // true
System.out.println("aBc".matches("a((?i)b)c")); // true
System.out.println("ABc".matches("a((?i)b)c")); // false // 需求1:要求要么是3个小写字母,要么是3个数字。
System.out.println("abc".matches("[a-z]{3}|\\d{3}")); // true
System.out.println("ABC".matches("[a-z]{3}|\\d{3}")); // false
System.out.println("123".matches("[a-z]{3}|\\d{3}")); // true
System.out.println("A12".matches("[a-z]{3}|\\d{3}")); // false // 需求2:必须是”我爱“开头,中间可以是至少一个”编程“,最后至少是1个”666“
System.out.println("我爱编程编程666666".matches("我爱(编程)+(666)+"));
System.out.println("我爱编程编程66666".matches("我爱(编程)+(666)+"));
}
}

4.3 正则表达式应用案例

学习完正则表达式的规则之后,接下来我们再利用正则表达式,去校验几个实际案例。

  • 正则表达式校验手机号码
/**
* 目标:校验用户输入的电话、邮箱、时间是否合法。
*/
public class RegexTest3 {
public static void main(String[] args) {
checkPhone();
} public static void checkPhone(){
while (true) {
System.out.println("请您输入您的电话号码(手机|座机): ");
Scanner sc = new Scanner(System.in);
String phone = sc.nextLine();
// 18676769999 010-3424242424 0104644535
if(phone.matches("(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})")){
System.out.println("您输入的号码格式正确~~~");
break;
}else {
System.out.println("您输入的号码格式不正确~~~");
}
}
}
}
  • 使用正则表达式校验邮箱是否正确
public class RegexTest3 {
public static void main(String[] args) {
checkEmail();
} public static void checkEmail(){
while (true) {
System.out.println("请您输入您的邮箱: ");
Scanner sc = new Scanner(System.in);
String email = sc.nextLine();
/**
* dlei0009@163.com
* 25143242@qq.com
* itheima@itcast.com.cn
*/
if(email.matches("\\w{2,}@\\w{2,20}(\\.\\w{2,10}){1,2}")){
System.out.println("您输入的邮箱格式正确~~~");
break;
}else {
System.out.println("您输入的邮箱格式不正确~~~");
}
}
}
}

4.4 正则表达式信息爬取

各位小伙伴,在前面的课程中,我们学习了正则表达式的作用之一,用来校验数据格式的正确性。接下来我们学习正则表达式的第二个作用:在一段文本中查找满足要求的内容

我们还是通过一个案例给大家做演示:案例需求如下

/**
* 目标:掌握使用正则表达式查找内容。
*/
public class RegexTest4 {
public static void main(String[] args) {
method1();
} // 需求1:从以下内容中爬取出,手机,邮箱,座机、400电话等信息。
public static void method1(){
String data = " 来黑马程序员学习Java,\n" +
" 电话:1866668888,18699997777\n" +
" 或者联系邮箱:boniu@itcast.cn,\n" +
" 座机电话:01036517895,010-98951256\n" +
" 邮箱:bozai@itcast.cn,\n" +
" 邮箱:dlei0009@163.com,\n" +
" 热线电话:400-618-9090 ,400-618-4000,4006184000,4006189090";
// 1、定义爬取规则
String regex = "(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})|(\\w{2,}@\\w{2,20}(\\.\\w{2,10}){1,2})"
+ "|(400-?\\d{3,7}-?\\d{3,7})";
// 2、把正则表达式封装成一个Pattern对象
Pattern pattern = Pattern.compile(regex);
// 3、通过pattern对象去获取查找内容的匹配器对象。
Matcher matcher = pattern.matcher(data);
// 4、定义一个循环开始爬取信息
while (matcher.find()){
String rs = matcher.group(); // 获取到了找到的内容了。
System.out.println(rs);
}
}
}

4.5 正则表达式搜索、替换

接下来,我们学习一下正则表达式的另外两个功能,替换、分割的功能。需要注意的是这几个功能需要用到Stirng类中的方法。这两个方法其实我们之前学过,只是当时没有学正则表达式而已。

/**
* 目标:掌握使用正则表达式做搜索替换,内容分割。
*/
public class RegexTest5 {
public static void main(String[] args) {
// 1、public String replaceAll(String regex , String newStr):按照正则表达式匹配的内容进行替换
// 需求1:请把下面字符串中的不是汉字的部分替换为 “-”
String s1 = "古力娜扎ai8888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴";
System.out.println(s1.replaceAll("\\w+", "-")); // 需求2(拓展):某语音系统,收到一个口吃的人说的“我我我喜欢编编编编编编编编编编编编程程程!”,需要优化成“我喜欢编程!”。
String s2 = "我我我喜欢编编编编编编编编编编编编程程程";
System.out.println(s2.replaceAll("(.)\\1+", "$1")); // 2、public String[] split(String regex):按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。
// 需求1:请把下面字符串中的人名取出来,使用切割来做
String s3 = "古力娜扎ai8888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴";
String[] names = s3.split("\\w+");
System.out.println(Arrays.toString(names));
}
}

Lambda表达式、方法引用、算法、正则表达式的更多相关文章

  1. 函数式接口 & lambda表达式 & 方法引用

    拉呱: 终于,学习jdk8的新特性了,初体验带给我的感觉真爽,代码精简的不行,可读性也很好,而且,spring5也是把jdk8的融入到血液里,总之一句话吧,说的打趣一点,学的时候自己难受,学完了写出来 ...

  2. java8之lambda表达式&方法引用(一)

    本文将简单的介绍一下Lambda表达式和方法引用,这也是Java8的重要更新,Lambda表达式和方法引用最主要的功能是为流(专门负责迭代数据的集合)服务. 什么是lambda表达式 可以把lambd ...

  3. 黑马Lambda表达式学习 Stream流 函数式接口 Lambda表达式 方法引用

  4. 黑马方法引用学习 Stream流 函数式接口 Lambda表达式 方法引用

  5. 黑马函数式接口学习 Stream流 函数式接口 Lambda表达式 方法引用

  6. 黑马Stream流学习 Stream流 函数式接口 Lambda表达式 方法引用

  7. 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

    作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...

  8. [转]深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

    以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-l ...

  9. lambda与方法引用

    哈喽,大家好,我是指北君. 虽然目前Java最新版本都已经到16了,但是绝大部分公司目前用的Java版本都是8,想当初Java8问世后,其Lambda表达式与方法引用可是最亮眼的新特性,目前,这两个特 ...

  10. Java8特性之Lambda、方法引用以及Stream流

    Java 8 中的 Streams API 详解:https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/ Java笔记——Jav ...

随机推荐

  1. Java和LWJGL的关于OpenAL的文章

    一.OpenAL的原理和基本概念: 1.1 OpenAL的架构 OpenAL的架构同样基于三个核心组件:Context(上下文).Source(声源)和Buffer(缓冲区).Context代表了音频 ...

  2. Mysql 不用Json存储 List<Long>的方式

    public static void main(String[] args) { List<Long> idList = new ArrayList<>(); for (int ...

  3. Java IO流的简单使用 通俗易懂 超详细 【内含案例】

    IO流简单使用 InputStream 字节输入流 OutputStream 字节输出流 Reader 字符输入流 Writer 字符输出流 代码示例 输入和输出是相对于程序来说的,读取到程序中叫做输 ...

  4. CRC算法原理、推导及实现

    CRC, Cyclic Redundancy Check, 循环冗余校验 1. 基本原理 CRC的本质是除法,把待检验的数据当作一个很大(很长)的被除数,两边选定一个除数(有的文献叫poly),最后得 ...

  5. Mybats写xml文件时传入参数为Integer类型的0被if标签判断为空bug

    当type = 0 时出现bug 不走这个条件 <if test='type != null and type!= ""' > and type = #{type} & ...

  6. 在 Ubuntu 环境下 Qt Creator 无法使用搜狗输入法

    在 Ubuntu 环境下 Qt Creator 无法使用搜狗输入法 在 Ubuntu 中安装 Qt Creator 后,发现无法使用搜狗输入法.切换输入法也没有效果. 最初以为是搜狗输入法出了问题,后 ...

  7. 【Mac】之安装VM虚拟机并安装centos7系统

    参考文章:<Mac 安装VMware Fusion虚拟机> 一.安装VMware Fusion 首先下载Mac版VMware虚拟机: 链接:https://pan.baidu.com/s/ ...

  8. 折腾 Quickwit,Rust 编写的分布式搜索引擎 - 可观测性之分布式追踪

    概述 分布式追踪是一种跟踪应用程序请求流经不同服务(如前端.后端.数据库等)的过程.它是一个强大的工具,可以帮助您了解应用程序的工作原理并调试性能问题. Quickwit 是一个用于索引和搜索非结构化 ...

  9. vue 报错 Component template should contain exactly one root element. If you are using v-if on multiple elements

    vue 报错 Component template should contain exactly one root element. If you are using v-if on multiple ...

  10. Go 必知必会:探索 Go 语言中的数组和切片深入理解顺序集合

    文末有面经共享群 在 Go 语言的丰富数据类型中,数组和切片是处理有序数据集合的强大工具,它们允许开发者以连续的内存块来存储和管理相同类型的多个元素.无论是在处理大量数据时的性能优化,还是在实现算法时 ...