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
import com.qunong.java8.entity.Employee;import org.junit.Test;import java.util.*;public class TestLambda {// 原来的匿名内部类@Testpublic void test1() {Comparator<Integer> com = new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return Integer.compare(o1, o2);}};TreeSet<Integer> ts = new TreeSet<>(com);}// Lambda 表达式@Testpublic void test2() {Comparator<Integer> com = (x, y) -> Integer.compare(x, y);TreeSet<Integer> ts = new TreeSet<>(com);}List<Employee> employeeList = Arrays.asList(new Employee("张三", 55, 7000),new Employee("李四", 46, 4000),new Employee("王五", 23, 8500),new Employee("赵六", 34, 5200),new Employee("田七", 27, 3000));// 需求:获取公司中员工年龄大于35的员工信息@Testpublic void test3() {List<Employee> list = filterEmployees(employeeList);for (Employee employee : list) {System.out.println(employee);}}public List<Employee> filterEmployees(List<Employee> list) {ArrayList<Employee> emps = new ArrayList<>();for (Employee employee : list) {if (employee.getAge() >= 35) {emps.add(employee);}}return emps;}// 优化方式一:策略设计模式@Testpublic void test4() {List<Employee> employees = filterEmployee(employeeList, new FilterEmployeeByAge());for (Employee employee : employees) {System.out.println(employee);}System.out.println(" ======================= ");List<Employee> employees1 = filterEmployee(employeeList, new FilterEmployeeBySalary());for (Employee employee : employees1) {System.out.println(employee);}}public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> mp) {List<Employee> emps = new ArrayList<>();for (Employee employee : list) {if (mp.test(employee)) {emps.add(employee);}}return emps;}// 优化方式二:匿名内部类@Testpublic void test5() {List<Employee> employeeList = filterEmployee(this.employeeList, new MyPredicate<Employee>() {@Overridepublic boolean test(Employee employee) {return employee.getSalary() >= 5000;}});for (Employee employee : employeeList) {System.out.println(employee);}}// 优化方式三:Lambda 表达式@Testpublic void test6() {// 依靠策略设计模式,接口,方法List<Employee> employees = filterEmployee(employeeList, (e) -> e.getSalary() >= 5000);employees.forEach(System.out::println);}// 优化方式四:Stream API@Testpublic void test7() {employeeList.stream().filter(e -> e.getSalary() >= 5000).limit(2).forEach(System.out::println);System.out.println(" =========================== ");employeeList.stream().map(Employee::getName).forEach(System.out::println);}}
Employee.java
import lombok.Getter;import lombok.Setter;import lombok.ToString;import lombok.experimental.Accessors;@Setter@Getter@ToString@Accessors(chain = true)public class Employee {private String name;private int age;private double salary;public Employee(String name, int age, double salary) {this.name = name;this.age = age;this.salary = salary;}}
策略设计模式,解决代码冗余
public interface MyPredicate<T> {boolean test(T t);}public class FilterEmployeeByAge implements MyPredicate<Employee> {@Overridepublic boolean test(Employee e) {return e.getAge() >= 35;}}public class FilterEmployeeBySalary implements MyPredicate<Employee> {@Overridepublic boolean test(Employee e) {return e.getSalary() >= 5000;}}
3,Lambda 基础语法
一:Lambda 表达式的基础语法:
Java8 中引入了一个新的操作符:“->”,即箭头操作符 或 Lambda 操作符。箭头操作符将 Lambda 表达式拆分成两部分。
左侧:Lambda 表达式的参数列表;
右侧:Lambda 表达式所需要执行的功能,即 Lambda 体
// 语法格式一:无参数,无返回值()->System.out.println("Hello Lambda.");// 语法格式二:有一个参数,并且无返回值(e) -> System.out.println(e);// 语法格式三:有一个参数时,小括号可以忽略e -> System.out.println(e);// 语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句Comparator<Integer> com = (x, y) -> {System.out.println("函数式接口.");return Integer.compare(x, y);};// 语法格式五:若 Lambda 体中只有一条语句,return 和 大括号都可以省略不写Comparator<Integer> com = (x, y) -> Integer.compare(x, y);// 语法格式六:Lambda 表达式的参数列表的数据类型可以忽略不写,// 因为JVM 编译器通过上下文推断出 数据类型,即“类型推断”(Integer x, Integer y) -> Integer.compare(x, y);口诀:左右遇一括号省,左侧推断类型省
二:Lambda 表达式需要“函数式接口”的支持
函数式接口:接口中只有一个抽象方法的接口,称为 函数式接口。
可以使用注解 @FunctionalInterface 修饰,可以检查是否是函数式接口
示例代码:
import org.junit.Test;import java.util.Comparator;import java.util.function.Consumer;/*** 一:Lambda 表达式的基础语法:Java8 中引入了一个新的操作符:“->”,即箭头操作符 或 Lambda 操作符* 箭头操作符将 Lambda 表达式拆分成两部分。* 左侧:Lambda 表达式的参数列表* 右侧:Lambda 表达式所需要执行的功能,即 Lambda 体* <p>* 语法格式一:无参数,无返回值* ()->System.out.println("Hello Lambda.");* <p>* 语法格式二:有一个参数,并且无返回值* (e) -> System.out.println(e);* <p>* 语法格式三:有一个参数时,小括号可以忽略* e -> System.out.println(e);* <p>* 语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句* Comparator<Integer> com = (x, y) -> {* System.out.println("函数式接口.");* return Integer.compare(x, y);* };* <p>* 语法格式五:若 Lambda 体中只有一条语句,return 和 大括号都可以省略不写* Comparator<Integer> com = (x, y) -> Integer.compare(x, y);* <p>* 语法格式六:Lambda 表达式的参数列表的数据类型可以忽略不写,因为JVM 编译器通过上下文推断出 数据类型,即“类型推断”* (Integer x, Integer y) -> Integer.compare(x, y);* <p>* 对联:* 左右遇一括号省* 左侧推断类型省* <p>* 二:Lambda 表达式需要“函数式接口”的支持* 函数式接口:接口中只有一个抽象方法的接口,称为 函数式接口。可以使用注解 @FunctionalInterface 修饰,可以检查是否是函数式接口*/public class TestLambda2 {@Testpublic void test1() {// final int num = 10;int num = 10;Runnable ra1 = new Runnable() {@Overridepublic void run() {System.out.println("Hello Lambda." + num);}};ra1.run();System.out.println(" ======================= ");Runnable ra2 = () -> System.out.println("Hello Lambda." + num);ra2.run();}@Testpublic void test2() {// new 实例Consumer<String> consumer = e -> System.out.println(e);// 调用方法consumer.accept("我加多酷威武。");}@Testpublic void test3() {Comparator<Integer> com = (x, y) -> {System.out.println("函数式接口.");return Integer.compare(x, y);};}@Testpublic void test4() {Comparator<Integer> com = (x, y) -> Integer.compare(x, y);}@Testpublic void test5() {Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y);}// 需求:对一个数进行运算@Testpublic void test6() {Integer val1 = operation(100, (x) -> x * x);System.out.println(val1);Integer val2 = operation(200, (x) -> x + x);System.out.println(val2);}public Integer operation(Integer num, MyFun mf) {return mf.getValue(num);}}
