1,Java8新特性;

1.1,速度更快;
1.2,代码更少(增加了新的语法 Lambda 表达式);
1.3,强大的 Stream API;
1.4,便于并行;
1.5,最大化减少空指针异常 Optional。

2,Lambda 表达式

1,为什么使用 Lambda 表达式?

Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。
可以写出更简洁,更灵活的代码。
作为一种更紧凑的代码风格,使 Java 的语言表达能力得到了提升。

2,练习(预热)

demo.java

  1. import com.qunong.java8.entity.Employee;
  2. import org.junit.Test;
  3. import java.util.*;
  4. public class TestLambda {
  5. // 原来的匿名内部类
  6. @Test
  7. public void test1() {
  8. Comparator<Integer> com = new Comparator<Integer>() {
  9. @Override
  10. public int compare(Integer o1, Integer o2) {
  11. return Integer.compare(o1, o2);
  12. }
  13. };
  14. TreeSet<Integer> ts = new TreeSet<>(com);
  15. }
  16. // Lambda 表达式
  17. @Test
  18. public void test2() {
  19. Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
  20. TreeSet<Integer> ts = new TreeSet<>(com);
  21. }
  22. List<Employee> employeeList = Arrays.asList(
  23. new Employee("张三", 55, 7000),
  24. new Employee("李四", 46, 4000),
  25. new Employee("王五", 23, 8500),
  26. new Employee("赵六", 34, 5200),
  27. new Employee("田七", 27, 3000)
  28. );
  29. // 需求:获取公司中员工年龄大于35的员工信息
  30. @Test
  31. public void test3() {
  32. List<Employee> list = filterEmployees(employeeList);
  33. for (Employee employee : list) {
  34. System.out.println(employee);
  35. }
  36. }
  37. public List<Employee> filterEmployees(List<Employee> list) {
  38. ArrayList<Employee> emps = new ArrayList<>();
  39. for (Employee employee : list) {
  40. if (employee.getAge() >= 35) {
  41. emps.add(employee);
  42. }
  43. }
  44. return emps;
  45. }
  46. // 优化方式一:策略设计模式
  47. @Test
  48. public void test4() {
  49. List<Employee> employees = filterEmployee(employeeList, new FilterEmployeeByAge());
  50. for (Employee employee : employees) {
  51. System.out.println(employee);
  52. }
  53. System.out.println(" ======================= ");
  54. List<Employee> employees1 = filterEmployee(employeeList, new FilterEmployeeBySalary());
  55. for (Employee employee : employees1) {
  56. System.out.println(employee);
  57. }
  58. }
  59. public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> mp) {
  60. List<Employee> emps = new ArrayList<>();
  61. for (Employee employee : list) {
  62. if (mp.test(employee)) {
  63. emps.add(employee);
  64. }
  65. }
  66. return emps;
  67. }
  68. // 优化方式二:匿名内部类
  69. @Test
  70. public void test5() {
  71. List<Employee> employeeList = filterEmployee(this.employeeList, new MyPredicate<Employee>() {
  72. @Override
  73. public boolean test(Employee employee) {
  74. return employee.getSalary() >= 5000;
  75. }
  76. });
  77. for (Employee employee : employeeList) {
  78. System.out.println(employee);
  79. }
  80. }
  81. // 优化方式三:Lambda 表达式
  82. @Test
  83. public void test6() {
  84. // 依靠策略设计模式,接口,方法
  85. List<Employee> employees = filterEmployee(employeeList, (e) -> e.getSalary() >= 5000);
  86. employees.forEach(System.out::println);
  87. }
  88. // 优化方式四:Stream API
  89. @Test
  90. public void test7() {
  91. employeeList.stream()
  92. .filter(e -> e.getSalary() >= 5000)
  93. .limit(2)
  94. .forEach(System.out::println);
  95. System.out.println(" =========================== ");
  96. employeeList.stream().map(Employee::getName).forEach(System.out::println);
  97. }
  98. }

Employee.java

  1. import lombok.Getter;
  2. import lombok.Setter;
  3. import lombok.ToString;
  4. import lombok.experimental.Accessors;
  5. @Setter
  6. @Getter
  7. @ToString
  8. @Accessors(chain = true)
  9. public class Employee {
  10. private String name;
  11. private int age;
  12. private double salary;
  13. public Employee(String name, int age, double salary) {
  14. this.name = name;
  15. this.age = age;
  16. this.salary = salary;
  17. }
  18. }

策略设计模式,解决代码冗余

  1. public interface MyPredicate<T> {
  2. boolean test(T t);
  3. }
  4. public class FilterEmployeeByAge implements MyPredicate<Employee> {
  5. @Override
  6. public boolean test(Employee e) {
  7. return e.getAge() >= 35;
  8. }
  9. }
  10. public class FilterEmployeeBySalary implements MyPredicate<Employee> {
  11. @Override
  12. public boolean test(Employee e) {
  13. return e.getSalary() >= 5000;
  14. }
  15. }

3,Lambda 基础语法

一:Lambda 表达式的基础语法:

Java8 中引入了一个新的操作符:“->”,即箭头操作符 或 Lambda 操作符。箭头操作符将 Lambda 表达式拆分成两部分。
左侧:Lambda 表达式的参数列表;
右侧:Lambda 表达式所需要执行的功能,即 Lambda 体

  1. // 语法格式一:无参数,无返回值
  2. ()->System.out.println("Hello Lambda.");
  3. // 语法格式二:有一个参数,并且无返回值
  4. (e) -> System.out.println(e);
  5. // 语法格式三:有一个参数时,小括号可以忽略
  6. e -> System.out.println(e);
  7. // 语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
  8. Comparator<Integer> com = (x, y) -> {
  9. System.out.println("函数式接口.");
  10. return Integer.compare(x, y);
  11. };
  12. // 语法格式五:若 Lambda 体中只有一条语句,return 和 大括号都可以省略不写
  13. Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
  14. // 语法格式六:Lambda 表达式的参数列表的数据类型可以忽略不写,
  15. // 因为JVM 编译器通过上下文推断出 数据类型,即“类型推断”
  16. (Integer x, Integer y) -> Integer.compare(x, y);
  17. 口诀:左右遇一括号省,左侧推断类型省

二:Lambda 表达式需要“函数式接口”的支持

函数式接口:接口中只有一个抽象方法的接口,称为 函数式接口。
可以使用注解 @FunctionalInterface 修饰,可以检查是否是函数式接口

示例代码:

  1. import org.junit.Test;
  2. import java.util.Comparator;
  3. import java.util.function.Consumer;
  4. /**
  5. * 一:Lambda 表达式的基础语法:Java8 中引入了一个新的操作符:“->”,即箭头操作符 或 Lambda 操作符
  6. * 箭头操作符将 Lambda 表达式拆分成两部分。
  7. * 左侧:Lambda 表达式的参数列表
  8. * 右侧:Lambda 表达式所需要执行的功能,即 Lambda 体
  9. * <p>
  10. * 语法格式一:无参数,无返回值
  11. * ()->System.out.println("Hello Lambda.");
  12. * <p>
  13. * 语法格式二:有一个参数,并且无返回值
  14. * (e) -> System.out.println(e);
  15. * <p>
  16. * 语法格式三:有一个参数时,小括号可以忽略
  17. * e -> System.out.println(e);
  18. * <p>
  19. * 语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
  20. * Comparator<Integer> com = (x, y) -> {
  21. * System.out.println("函数式接口.");
  22. * return Integer.compare(x, y);
  23. * };
  24. * <p>
  25. * 语法格式五:若 Lambda 体中只有一条语句,return 和 大括号都可以省略不写
  26. * Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
  27. * <p>
  28. * 语法格式六:Lambda 表达式的参数列表的数据类型可以忽略不写,因为JVM 编译器通过上下文推断出 数据类型,即“类型推断”
  29. * (Integer x, Integer y) -> Integer.compare(x, y);
  30. * <p>
  31. * 对联:
  32. * 左右遇一括号省
  33. * 左侧推断类型省
  34. * <p>
  35. * 二:Lambda 表达式需要“函数式接口”的支持
  36. * 函数式接口:接口中只有一个抽象方法的接口,称为 函数式接口。可以使用注解 @FunctionalInterface 修饰,可以检查是否是函数式接口
  37. */
  38. public class TestLambda2 {
  39. @Test
  40. public void test1() {
  41. // final int num = 10;
  42. int num = 10;
  43. Runnable ra1 = new Runnable() {
  44. @Override
  45. public void run() {
  46. System.out.println("Hello Lambda." + num);
  47. }
  48. };
  49. ra1.run();
  50. System.out.println(" ======================= ");
  51. Runnable ra2 = () -> System.out.println("Hello Lambda." + num);
  52. ra2.run();
  53. }
  54. @Test
  55. public void test2() {
  56. // new 实例
  57. Consumer<String> consumer = e -> System.out.println(e);
  58. // 调用方法
  59. consumer.accept("我加多酷威武。");
  60. }
  61. @Test
  62. public void test3() {
  63. Comparator<Integer> com = (x, y) -> {
  64. System.out.println("函数式接口.");
  65. return Integer.compare(x, y);
  66. };
  67. }
  68. @Test
  69. public void test4() {
  70. Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
  71. }
  72. @Test
  73. public void test5() {
  74. Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y);
  75. }
  76. // 需求:对一个数进行运算
  77. @Test
  78. public void test6() {
  79. Integer val1 = operation(100, (x) -> x * x);
  80. System.out.println(val1);
  81. Integer val2 = operation(200, (x) -> x + x);
  82. System.out.println(val2);
  83. }
  84. public Integer operation(Integer num, MyFun mf) {
  85. return mf.getValue(num);
  86. }
  87. }