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 {
// 原来的匿名内部类
@Test
public void test1() {
Comparator<Integer> com = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
};
TreeSet<Integer> ts = new TreeSet<>(com);
}
// Lambda 表达式
@Test
public 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的员工信息
@Test
public 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;
}
// 优化方式一:策略设计模式
@Test
public 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;
}
// 优化方式二:匿名内部类
@Test
public void test5() {
List<Employee> employeeList = filterEmployee(this.employeeList, new MyPredicate<Employee>() {
@Override
public boolean test(Employee employee) {
return employee.getSalary() >= 5000;
}
});
for (Employee employee : employeeList) {
System.out.println(employee);
}
}
// 优化方式三:Lambda 表达式
@Test
public void test6() {
// 依靠策略设计模式,接口,方法
List<Employee> employees = filterEmployee(employeeList, (e) -> e.getSalary() >= 5000);
employees.forEach(System.out::println);
}
// 优化方式四:Stream API
@Test
public 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> {
@Override
public boolean test(Employee e) {
return e.getAge() >= 35;
}
}
public class FilterEmployeeBySalary implements MyPredicate<Employee> {
@Override
public 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 {
@Test
public void test1() {
// final int num = 10;
int num = 10;
Runnable ra1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello Lambda." + num);
}
};
ra1.run();
System.out.println(" ======================= ");
Runnable ra2 = () -> System.out.println("Hello Lambda." + num);
ra2.run();
}
@Test
public void test2() {
// new 实例
Consumer<String> consumer = e -> System.out.println(e);
// 调用方法
consumer.accept("我加多酷威武。");
}
@Test
public void test3() {
Comparator<Integer> com = (x, y) -> {
System.out.println("函数式接口.");
return Integer.compare(x, y);
};
}
@Test
public void test4() {
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
}
@Test
public void test5() {
Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y);
}
// 需求:对一个数进行运算
@Test
public 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);
}
}