1.Lambda表达式
1.1 为什么使用lambda表达式
package com.magic.java8;
import lombok.*;
import org.junit.Test;
import java.util.*;
//需求1:获取年纪大于35的人
//需求2:获取工资大于6000的人
//在这个类里面根据需求不断写方法,如果继续追加需求呢?怎么优化?
//优化方式1:策略设计模式,一个接口多个实现类,只需要在LambdaDemo类写一个方法,调不同实现类即可
//优化方式2:匿名内部类,在1的基础上使用匿名内部类
//优化方式3:lambda表达式,在2的基础上使用lambda表达式简化
@Data
@Getter
class Employee{
private int age;
private String name;
private double salary;
public Employee() {
}
public Employee(int age) {
this.age = age;
}
public Employee(int age, String name, double salary) {
this.age = age;
this.name = name;
this.salary = salary;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
public class LambdaDemo {
//原来的匿名内部类
@Test
public void test01(){
Comparator<Integer> com = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return 0;
}
};
TreeSet<Integer> treeSet = new TreeSet<>(com);
}
//lambda表达式
@Test
public void test02(){
Comparator<Integer> com = (x,y) ->Integer.compare(x,y);
TreeSet<Integer> treeSet = new TreeSet<>(com);
}
List<Employee> list = Arrays.asList(new Employee(18,"ss",9999.99),
new Employee(18,"ds",8999.99),
new Employee(50,"hh",9999.99),
new Employee(48,"pp",6999.99),
new Employee(38,"ww",4999.99)
);
public List<Employee> filterEmployeeList(List<Employee> list,MyPredicate<Employee> mp){
List<Employee> employeeList = new ArrayList<>();
for (Employee e : list){
if(mp.test(e)){
employeeList.add(e);
}
}
return employeeList;
}
@Test
public void test06(){
List<Employee> employeeList = filterEmployeeList(list,employee -> employee.getSalary()>5000);
System.out.println(employeeList);
}
//简化的流式代码
@Test
public void test07(){
list.stream()
.filter(employee -> employee.getSalary()>5000)
.limit(2)
.forEach(System.out::println);
list.stream().map(Employee::getSalary).forEach(System.out::println);
}
}
package com.magic.java8;
public interface MyPredicate<T> {
public boolean test(T t);
}
1.2 lambda表达式的基本语法
lambda表达式基础语法:java8中引入了一个新的操作符“->”该操作符称为箭头操作符或者lambda操作符
操作符分为两部分:
- 左侧:参数列表
- 右侧:lambda表达式中所需执行的功能,即lambda体
- 语法格式1: 无参无返回值
()-> System.out.println("hello lambda")
- 语法格式2: 一个参数,无返回值
(x)-> System.out.println(x)
- 语法格式3: 有且只有一个参数,()可以省略
x-> System.out.println(x)
- 语法格式4:有两个以上参数,有返回值,并且lambda体中有多条语句
Comparator<Integer> comparator = (x,y)->{
System.out.println("test");
return Integer.compare(x,y);
};
- 语法格式5:若只有一条语句,{}和return都可以省略不写
Comparator<Integer> comparator = (x,y)->Integer.compare(x,y);
- 语法格式6:参数列表的数据类型可以省略不写,因为jvm编译器可以通过上下文推断出数据类型,即“类型推断”
package com.magic.java8;
import org.junit.Test;
import java.util.Comparator;
/**
* @Description
* @Author Chelsea
* @Date 2020/2/1 18:52
*/
public class LambdaSyntax {
public void test01(){
int num = 0;//jdk1.7之前必须是final,现在没有但是实际上也是不可修改的
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("hello world"+num);
}
};
Runnable runnable1 = ()-> System.out.println("hello lambda");
}
@Test
public void test04(){
Comparator<Integer> comparator = (x,y)->{
System.out.println("test");
return Integer.compare(x,y);
};
}
@Test
public void test05(){
Comparator<Integer> comparator = (x,y)->Integer.compare(x,y);
}
@Test
public void test07(){
Integer result = operation(100,num -> num+num);
System.out.println(result);
}
public Integer operation(Integer num,MyFun myFun){
return myFun.getValue(num);
}
}
package com.magic.java8;
@FunctionalInterface
public interface MyFun {
public Integer getValue(Integer num);
}
lambda表达式需要函数式接口的支持
函数式接口:接口中只有一个抽象方法的接口,可以使用注解@FunctionalInterface修饰,可以检查是否是函数式接口
2.四大内置核心函数式接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer消费型接口 | T | void | 对类型为T的对象应用操作,包含方法:void accept(T t) |
Supplier供给型接口 | 无 | T | 返回类型为T的对象,包含方法:T get() |
Function<T,R>函数型接口 | T | R | 对类型为T的对象应用操作,并返回结果是R类型的对象。包含方法:R apply(T t) |
Predicate断定型接口 | T | boolean | 确定类型为T的对象是否满足某约束,并返回boolean值。包含方法:boolean test(T t) |
package com.magic.java8;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* @Description
* @Author Chelsea
* @Date 2020/2/1 20:03
*
* Consumer<T>:消费型接口
* void accept(T t)
* Supplier<T>:供给型接口
* T get()
* Function<T,R>:函数型接口
* R apply(T t)
* Prediction<T>:断言型接口
* boolean test(T t)
*/
public class FourCoreInterfaceDemo {
//Consumer
@Test
public void test01(){
happy(1000,(m)->System.out.println("happy"+m));
}
public void happy(double money, Consumer<Double> consumer){
consumer.accept(money);
}
//Supplier
@Test
public void test02(){
List<Integer> numList = getNumList(10, () -> (int)( Math.random() * 100));
for(Integer i : numList){
System.out.println(i);
}
}
public List<Integer> getNumList(Integer num, Supplier<Integer> supplier){
List<Integer> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
Integer n = supplier.get();
list.add(n);
}
return list;
}
//Function
@Test
public void test03(){
System.out.println(strHandler("adadas", (s -> s.substring(1, 3))));
}
public String strHandler(String str, Function<String,String> fn){
return fn.apply(str);
}
//Predicate
@Test
public void test04(){
List<String> list = Arrays.asList("qw","www","ok","eeeerg");
List<String> strList = filterStr(list,(s)->s.length()<3);
for (String a : strList){
System.out.println(a);
}
}
public List<String> filterStr(List<String> list, Predicate<String> predicate){
List<String> strList = new ArrayList<>();
for (String str: list){
if(predicate.test(str)){
strList.add(str);
}
}
return strList;
}
}
3.对象引用、构造器引用、数组引用
3.1 方法引用
- 方法引用:若lambda体中的内容有方法已经实现了,我们可以使用“方法引用”(可以理解为方法引用是lambda表达式的另一种表达形式)
- 主要有三种语法格式
- 对象::实例方法名
- 类::静态方法名
- 类::实例方法名
- 注意事项:
- lambda体中调用方法的参数列表与返回值类型,与函数式接口中抽象方法的函数列表和返回值类型保持一致
- 若lambda参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method
3.2构造器引用
- 格式: ClassName::new
- 注意事项:需要调用的构造器参数列表要与函数式接口中的抽象方法的参数列表保持一致
3.3数组引用
见下面代码
package com.magic.java8;
import org.junit.Test;
import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class MethodRefDemo {
@Test
public void test1(){
Consumer<String> consumer = (x)-> System.out.println(x);
PrintStream ps = System.out;
Consumer consumer1 = ps::println;
}
@Test
public void test2(){
Comparator<Integer> comparator = (x,y)->Integer.compare(x,y);
Comparator<Integer> comparator2 = Integer::compare;
}
@Test
public void test3(){
BiPredicate<String,String> bp = (x,y)->x.equals(y);
BiPredicate<String,String> bp1 = String::equals;
}
//构造器引用
@Test
public void test4(){
Supplier<Employee> supplier = ()->new Employee();
Supplier<Employee> sup2 = Employee::new;
Employee employee = sup2.get();
System.out.println(employee);
}
@Test
public void test5(){
Function<Integer,Employee> function = (x)->new Employee(x);
Function<Integer,Employee> function2 = Employee::new;
}
//数组引用
@Test
public void test6(){
Function<Integer,String[]> function = (x)->new String[x];
String [] strs = function.apply(10);
System.out.println(strs.length);
Function<Integer,String[]> fun2 = String[]::new;
String[] strs2 = fun2.apply(20);
System.out.println(strs2.length);
}
}
学习整理于Java8新特性.