目录
- package com.jiayifeng.java;
-
- import org.junit.Test;
-
- import java.util.Comparator;
- import java.util.function.Consumer;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-19 12:29
- *
- * 一:Lambda表达式的使用
- * 1.举例:(o1,o2) -> Integer.compare(o1,o2);
- * 2.格式:
- * "->":Lambda操作符或箭头操作符
- * "->"左边:Lambda形参列表(也就是接口中的抽象方法的形参列表)
- * "->"左边:Lambda体(也就是重写的抽象方法的方法体)
- *
- * 3.Lambda表达式的使用:(六种情况)
- *
- * 4.Lambda表达式的本质:作为函数式接口的实例
- * 如果一个接口中只声明了一个抽象方法,则此接口就称之为函数式接口。
- * 我们可以在一个接口上使用@FunctionalInterface注解,这样可以检验它
- * 是否是一个函数式接口
- *
- *
- * 5.总结
- * "->"左边:Lambda形参列表的参数类型可以省略(类型推断);
- * 如果Lambda形参列表只有一个参数,其一对()也可以省略
- * "->"右边:Lambda体应使用一对{}包裹;
- * 如果Lambda体只有一条执行语句(也可能是return语句),可以省略这一对{}和return关键字
- *
- */
- public class Lambda {
- @Test
- public void test1(){
- Runnable r1 = new Runnable(){
- @Override
- public void run() {
- System.out.println("我爱北京天安门!");
- }
- };
- r1.run();
- System.out.println("************");
-
- // Lambda表达式的写法
- Runnable r2 = () -> System.out.println("我爱北京故宫!");
- r2.run();
- System.out.println("************");
-
- // 方法引用
- Comparator
com3 = Integer::compare; - int compare = com3.compare(32, 21);
- System.out.println(compare);
- }
-
- // 语法格式一:无参、无返回值
- @Test
- public void test2(){
- Runnable r1 = new Runnable(){
- @Override
- public void run() {
- System.out.println("我爱北京天安门!");
- }
- };
- r1.run();
- System.out.println("************");
-
- // Lambda表达式的写法
- Runnable r2 = () -> {
- System.out.println("我爱北京故宫!");
- };
- r2.run();
- }
-
- // 语法格式二:Lambda需要一个参数,但是没有返回值
- @Test
- public void test3(){
- Consumer
con = new Consumer() { -
- @Override
- public void accept(String s) {
- System.out.println(s);
- }
- };
- con.accept("谎言和誓言的区别是什么?");
- System.out.println("**************");
-
- Consumer
con1 = (String s) -> { - System.out.println(s);
- };
- con1.accept("一个是听的人当真了,一个是说的人当真了");
- }
-
- // 语法格式三:数据类型可以省略,因为可由编译推断得出,称为“类型推断”
- @Test
- public void test4(){
- Consumer
con1 = (String s) -> { - System.out.println(s);
- };
- con1.accept("一个是听的人当真了,一个是说的人当真了");
- System.out.println("******************");
-
- Consumer
con2 = (s) -> { - System.out.println(s);
- };
- con1.accept("一个是听的人当真了,一个是说的人当真了!");
- }
-
- // 语法格式四:Lambda若只需要一个参数时,参数的小括号可以省略
- @Test
- public void test5(){
- Consumer
con1 = s -> { - System.out.println(s);
- };
- con1.accept("一个是听的人当真了,一个是说的人当真了");
- }
-
- // 语法格式五:Lambda需要两个或两个以上的参数,多条执行语句,并且可以有返回值
- @Test
- public void test6() {
- Comparator
com1 = new Comparator() { -
- @Override
- public int compare(Integer o1, Integer o2) {
- System.out.println(o1);
- System.out.println(o2);
- return o1.compareTo(o2);
- }
- };
- System.out.println(com1.compare(12,21));
- System.out.println("**************");
-
- Comparator
com2 = (o1, o2) -> { - System.out.println(o1);
- System.out.println(o2);
- return o1.compareTo(o2);
- };
- System.out.println(com2.compare(12,6));
- }
-
- // 语法格式六:当Lambda体只有一条语句时,return与大括号若有,都可以省略
- @Test
- public void test7(){
- Comparator
com1 = (o1, o2) -> { - return o1.compareTo(o2);
- };
- System.out.println(com1.compare(12,6));
- System.out.println("***********");
-
- Comparator
com2 = (o1, o2) -> o1.compareTo(o2); - System.out.println(com1.compare(12,9));
- }
- }
| 函数式接口 | 参数类型 | 返回类型 | 用途 |
| Consumer | T | void | 对类型为T的对象应用操作,包含方法:void accept(T t) |
| Supplier | 无 | T | 返回类型为T的对象,包含方法:T get() |
| Function | T | R | 对类型为T的对象应用操作,并返回结果,结果是R类型的对象。包含方法:R apply(T t) |
| Predicate | T | boolean | 确定类型为T的对象是否满足某约束,并返回boolean值。包含方法:boolean test(T t) |
- package com.jiayifeng.java;
-
- import org.junit.Test;
-
- import java.util.function.Consumer;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-19 16:51
- *
- * 一:Java内置的四大核心函数式接口
- */
- public class LambdaTest1 {
- @Test
- public void test1(){
- happyTime(500, new Consumer
() { - @Override
- public void accept(Double aDouble) {
- System.out.println("学习太累了,去超市买瓶水,价格为:" + aDouble);
- }
- });
- System.out.println("**************");
-
- happyTime(400,money -> System.out.println("学习太累了,去超市喝了瓶水,价格为:" + money));
- }
-
- public void happyTime(double money, Consumer
con) { - con.accept(money);
- }
- }
- package com.jiayifeng.java;
-
- import org.junit.Test;
-
- import java.io.PrintStream;
- import java.util.function.Consumer;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-19 17:10
- *
- * 一:方法引用和构造器引用
- * 1.使用情景:当要传递给Lambda体的操作已经有实现的方法了,可以使用方法引用
- * 2.方法引用,本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例。
- * 所以方法引用,也是函数式接口的实例
- * 3.使用格式:类(或对象) :: 方法名
- * 4.具体分为如下的三种情况:
- * 对象 :: 非静态方法
- * 类 :: 静态方法
- * 类 :: 非静态方法
- * 5.方法引用使用的要求:要求接口中的抽象方法的形参列表和返回值类型与
- * 方法引用的方法的形参列表和返回值类型相同(针对于前两种情况)
- */
- public class MethodRefTest {
- @Test
- public void test1(){
- // 情况一:对象 :: 实例方法
- // Consumer中的void accept(T t)
- // PrintStream中的void Println(T t)
- Consumer
con1 = str -> System.out.println(str); - con1.accept("北京");
- System.out.println("**********");
-
- PrintStream ps = System.out;
- Consumer
con2 = ps :: println; - con2.accept("beijing");
- }
- }
构造器引用:
和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致
数组引用:
可以将数组看做是一个特殊的类,写法与构造器引用一致
使用Stream API对数据集合进行操作,就类似于使用SQL执行的数据库查询
简言之:Stream API提供了一种高效且易于使用的处理数据的方式
定义:Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列
“集合讲的是数据,Stream讲的是计算”
注意:
①Stream自己不会存储数据
②Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream
③Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行
执行流程:
- package com.jiayifeng.java;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-19 19:34
- */
- public class Employee {
-
- private int id;
- private String name;
- private int age;
- private double salary;
-
-
- public Employee(int id) {
- this.id = id;
- }
-
-
- public Employee(int id, String name, int age) {
- this.id = id;
- this.name = name;
- this.age = age;
- }
-
- public Employee(int id, String name) {
- this.id = id;
- this.name = name;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof Employee)) return false;
-
- Employee employee = (Employee) o;
-
- if (getId() != employee.getId()) return false;
- if (getAge() != employee.getAge()) return false;
- if (Double.compare(employee.getSalary(), getSalary()) != 0) return false;
- return getName() != null ? getName().equals(employee.getName()) : employee.getName() == null;
- }
-
- @Override
- public int hashCode() {
- int result;
- long temp;
- result = getId();
- result = 31 * result + (getName() != null ? getName().hashCode() : 0);
- result = 31 * result + getAge();
- temp = Double.doubleToLongBits(getSalary());
- result = 31 * result + (int) (temp ^ (temp >>> 32));
- return result;
- }
-
- @Override
- public String toString() {
- return "Employee{" +
- "id=" + id +
- ", name='" + name + '\'' +
- ", age=" + age +
- ", salary=" + salary +
- '}';
- }
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- public double getSalary() {
- return salary;
- }
-
- public void setSalary(double salary) {
- this.salary = salary;
- }
-
- public Employee() {
- }
-
- public Employee(int id, String name, int age, double salary) {
- this.id = id;
- this.name = name;
- this.age = age;
- this.salary = salary;
- }
- }
- package com.jiayifeng.java;
-
- import java.util.ArrayList;
- import java.util.List;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-19 19:35
- */
- public class EmployeeData {
- public static List
getEmp() { -
- List
list = new ArrayList<>(); - list.add(new Employee(1001, "马化腾", 34, 6000.38));
- list.add(new Employee(1002, "马云", 12, 9876.12));
- list.add(new Employee(1003, "刘强东", 33, 3000.82));
- list.add(new Employee(1004, "雷军", 26, 7657.37));
- list.add(new Employee(1005, "李彦宏", 65, 5555.21));
- list.add(new Employee(1006, "比尔盖茨", 42, 9500.43));
- list.add(new Employee(1006, "任正非", 26, 4333.32));
- list.add(new Employee(1006, "扎克伯格", 35, 2500.32));
- return list;
- }
- }
- package com.jiayifeng.java;
-
- import org.junit.Test;
-
- import java.util.Arrays;
- import java.util.List;
- import java.util.stream.IntStream;
- import java.util.stream.Stream;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-19 19:26
- *
- * 一:Stream API
- * 1.Stream关注的是对数据的运算,与CPU打交道
- * 集合关注的是数据的存储,与内存打交道
- *
- * 2.Stream执行流程
- * ①Stream实例化
- * ②一系列的中间操作(过滤、映射等)
- * ③终止操作
- *
- * 3.说明
- * ①一个中间操作链,对数据源的数据进行处理
- * ②一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被调用
- *
- */
- public class StreamAPI {
- /**
- * 创建Stream方式1:通过集合List
- */
- @Test
- public void test1() {
-
- List
emp = EmployeeData.getEmp(); - //通过集合来创建
- //顺序流
- Stream
stream = emp.stream(); - //并行流
- Stream
employeeStream = emp.parallelStream(); - }
-
- /**
- * 创建Stream方式2:通过数组
- */
- @Test
- public void test2() {
- int arr[] = new int[]{1, 2, 3, 4, 5, 6};
- //调用Arrays.stream返回数组
- IntStream stream = Arrays.stream(arr);
-
- Employee e1 = new Employee(1, "1", 1, 1);
- Employee e2 = new Employee(2, "1", 1, 1);
-
- Employee employees[] = new Employee[]{e1, e2};
- Stream
stream1 = Arrays.stream(employees); - }
-
-
- /**
- * 创建Stream方式3: 通过Stream的of()来创建
- */
- @Test
- public void test3() {
- Stream
integerStream = Stream.of(1, 2, 3, 4, 5, 6); - Stream extends Number> stream = Stream.of(1.0, 2, 3, 4, 5, 6);
- }
-
- /**
- * 创建Stream方式4:创建无限流
- */
- @Test
- public void test4() {
- //迭代
- //遍历前10个偶数
- Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
- //生成
- Stream.generate(Math::random).limit(10).forEach(System.out::println);
- }
- }
- package com.jiayifeng.java;
-
- import org.junit.Test;
-
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.stream.Stream;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-19 19:46
- *
- * 一:测试Stream的中间操作
- */
- public class StreamAPITest1 {
- // 1.筛选与切片
- @Test
- public void test1(){
- List
list = EmployeeData.getEmp(); - // filter(Predicate p):接收Lambda,从流中欧排除某些元素
- Stream
stream = list.stream(); - // 查询员工表中薪资大于7000的员工信息
- stream.filter(e -> e.getSalary() > 7000).forEach(System.out :: println);
- System.out.println();
-
- // limit(n):截断流,使其元素不超过给定数量
- list.stream().limit(3).forEach(System.out :: println);
- System.out.println();
-
- // skip(n):跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流
- list.stream().skip(3).forEach(System.out :: println);
- System.out.println();
-
- // distinct():筛选,通过流所生成元素的hashCode()和equals()去除重复元素
- list.add(new Employee(1010,"刘强东",40,8000));
- list.add(new Employee(1010,"刘强东",40,8000));
- list.add(new Employee(1010,"刘强东",40,8000));
- list.add(new Employee(1010,"刘强东",40,8000));
- list.add(new Employee(1010,"刘强东",40,8000));
- // System.out.println(list);
-
- list.stream().distinct().forEach(System.out :: println);
- }
-
- // 2.映射
- @Test
- public void test2(){
- // map(Function f):接受一个函数作为参数,将元素转换成其它形式或提取信息,该函数会
- // 被应用到每一个元素上,并将其映射成一个新的元素
- List
list = Arrays.asList("aa","bb","cc","dd"); - list.stream().map(str -> str.toUpperCase()).forEach(System.out :: println);
-
- // flatMap(Function f):接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有
- // 流连接成一个流
- ArrayList list1 = new ArrayList<>();
- list1.add(1);
- list1.add(2);
- list1.add(3);
-
- ArrayList list2 = new ArrayList();
- list2.add(4);
- list2.add(5);
- list2.add(6);
-
- list1.addAll(list2);
- System.out.println(list1);
- }
-
- // 3.排序
- @Test
- public void test3(){
- // sort():自然排序
- List
list = Arrays.asList(12, 45, 24, 46, 67, 98); - list.stream().sorted().forEach(System.out :: println);
-
- // 抛异常,原因:Employee没有实现Comparable接口
- // List
emp = EmployeeData.getEmp(); - // emp.stream().sorted().forEach(System.out :: println);
-
- // sorted(Compatater com):定制排序
- List
emp = EmployeeData.getEmp(); - emp.stream().sorted((e1,e2) -> Integer.compare(e1.getAge(),e2.getAge()))
- .forEach(System.out :: println);
-
- }
- }
- package com.jiayifeng.java1;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-21 11:49
- */
-
- public class Student {
- private int id;//id
- private String name;//姓名
- private int age;//年龄
- private Score score;//成绩(优秀、良好、及格)
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- public Score getScore() {
- return score;
- }
-
- public void setScore(Score score) {
- this.score = score;
- }
-
- public enum Score{
- EXCELLENT,
- GOOD,
- PASS
- }
-
- public Student(int id, String name, int age, Score score) {
- this.id = id;
- this.name = name;
- this.age = age;
- this.score = score;
- }
- }
- package com.jiayifeng.java1;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-21 11:50
- */
- import com.jiayifeng.java.Employee;
- import com.jiayifeng.java.EmployeeData;
- import org.junit.Test;
-
- import java.util.Arrays;
- import java.util.List;
- import java.util.Optional;
- import java.util.stream.Collectors;
- import java.util.stream.Stream;
-
- /**
- * @description: 终止操作
- * allMatch——检查是否匹配所有元素
- * anyMatch——检查是否至少匹配一个元素
- * noneMatch——检查是否没有匹配的元素
- * findFirst——返回第一个元素
- * findAny——返回当前流中的任意元素
- * count——返回流中元素的总个数
- * max——返回流中最大值
- * min——返回流中最小值
- * @author: xz
- */
- public class StreamTest {
- public static void main(String[] args) {
- List
studentsList = Arrays.asList( - new Student(1, "李四", 20,Student.Score.EXCELLENT),
- new Student(2, "张三", 19,Student.Score.GOOD ),
- new Student(3, "王五", 24,Student.Score.PASS),
- new Student(4, "赵六", 23, Student.Score.GOOD),
- new Student(5, "xz", 21, Student.Score.PASS )
- );
-
- //检查学生的成绩是都是良好
- boolean b = studentsList.stream()
- .allMatch(s -> s.getScore().equals(Student.Score.GOOD));
- System.out.println("allMatch——"+b);
-
- //检查学生的成绩至少有一个是良好
- boolean b1 = studentsList.stream()
- .anyMatch(s -> s.getScore().equals(Student.Score.GOOD));
- System.out.println("anyMatch——"+b1);
-
- //检查学生的成绩是否没有匹配到良好
- boolean b2 = studentsList.stream()
- .noneMatch(s -> s.getScore().equals(Student.Score.GOOD));
- System.out.println("noneMatch——"+b2);
-
- //按年龄排序且返回第一个元素
- Optional
op1 = studentsList.stream() - .sorted((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge()))
- .findFirst();
- System.out.println("findFirst(按年龄排序且返回第一个元素)——"+op1.get());
-
- //查找学生成绩为及格且返回的任意元素
- Optional
op2 = studentsList.parallelStream() - .filter(s -> s.getScore().equals(Student.Score.PASS))
- .findAny();
- System.out.println("findAny(查找学生成绩为及格且返回的任意元素)——"+op2.get());
-
- ///查找学生的总人数
- long count = studentsList.stream()
- .count();
- System.out.println("count——"+count);
-
- //查找年龄最大的学生信息
- Optional
op3 = studentsList.stream() - .max((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge()));
- System.out.println("max——"+op3.get());
-
- //查找学生所有的年龄范围,并获取最小的年龄
- Optional
op4 = studentsList.stream() - .map(Student::getAge)
- .min(Integer::compare);
- System.out.println("min——"+op4.get());
- }
- /*
- allMatch——false
- anyMatch——true
- noneMatch——false
- findFirst(按年龄排序且返回第一个元素)——com.jiayifeng.java1.Student@5f184fc6
- findAny(查找学生成绩为及格且返回的任意元素)——com.jiayifeng.java1.Student@34a245ab
- count——5
- max——com.jiayifeng.java1.Student@34a245ab
- min——19
- */
-
- // 规约
- @Test
- public void Test1(){
- // 练习一:计算1-10的自然数之和
- List
list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); - Integer sum = list.stream().reduce(0,Integer::sum);
- System.out.println(sum);//55
-
- // 练习二:计算公司所有员工工资的总和
- List
employees = EmployeeData.getEmp(); - Stream
salaryStream = employees.stream().map(Employee::getSalary); - Optional
sumMoney = salaryStream.reduce((d1, d2) -> (d1 + d2)); - System.out.println(sumMoney);
- }
-
- // 收集
- @Test
- public void test2(){
- List
emp = EmployeeData.getEmp(); - List
employeeList = emp.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList()); - employeeList.forEach(System.out::println);
- }
- }
Stream的详细介绍参考:http://t.csdnimg.cn/bAycz
为了解决空指针异常而引入Optional类
Optional类的javadoc描述如下:这是一个可以为null的容器对象。如果值存在,则isPresent()方法会返回true,调用get()方法会返回该对象
- package com.jiayifeng.java2;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-21 12:25
- */
- public class Girl {
- private String name;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Girl() {
- }
-
- @Override
- public String toString() {
- return "Girl{" +
- "name='" + name + '\'' +
- '}';
- }
-
- public Girl(String name) {
- this.name = name;
- }
- }
- package com.jiayifeng.java2;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-21 12:25
- */
- public class Boy {
- private Girl girl;
-
- public Boy(Girl girl) {
- this.girl = girl;
- }
-
- public Boy() {
- }
-
- @Override
- public String toString() {
- return "Boy{" +
- "girl=" + girl +
- '}';
- }
-
- public Girl getGirl() {
- return girl;
- }
-
- public void setGirl(Girl girl) {
- this.girl = girl;
- }
- }
- package com.jiayifeng.java2;
-
- import org.junit.Test;
-
- import java.util.Optional;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-21 12:27
- *
- * 一:Optional类:为了在程序中避免出现空指针异常而创建的
- */
- public class OptionalTest {
- @Test
- public void test1(){
- // 1.Optional.of(T t):创建一个Optional实例,t必须为空
- Girl girl = new Girl();
- Optional
girl1 = Optional.of(girl); -
- // 2.Optional.empty():创建一个空的Optional实例
-
- // 3.Optional.ofNullable(T t):t可以为空
- Girl girl2 = new Girl();
- girl2 = null;
- Optional
optionalGirlgirl1 = Optional.ofNullable(girl2); - System.out.println(optionalGirlgirl1);
- }
-
- public String getGirlName(Boy boy){
- Optional
boyOptional = Optional.ofNullable(boy); - // 此时的boy1一定非空
- Boy boy1 = boyOptional.orElse(new Boy(new Girl("迪丽热巴")));
-
- Girl girl1 = boy1.getGirl();
-
- Optional
girlOptional = Optional.ofNullable(girl1); - // girl2一定非空
- Girl girl2 = girlOptional.orElse(new Girl("古力娜扎"));
-
- return girl2.getName();
- }
-
- @Test
- public void test2(){
- Boy boy = null;
- boy = new Boy();
- boy = new Boy(new Girl("贾老师"));
- String girlName = getGirlName(boy);
- System.out.println(girlName);
- }
- }