Lambda表达式
1.Lambda表达式书写形式(箭头函数)
左边放的是需要传递的参数->右边放的是被改造方法的方法体
2.Lambda表达式的使用
1.使用条件
必须是函数式接口
函数式接口:接口中仅仅定义了一个抽象方法的接口。
JDK8推出的注解@FunctionalInterface可以确保被注释的接口是函数是接口
2.感受效果(下面代码是通过传统方式,接口,Lambda改造方式实现同一个需求)
package cn.wolfcode.annotation;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
/**
* @author: 阿落
* @date: 2022/8/22 22:59
*/
//需求:
//①获取所有性别为男的学生
//②获取所有成绩不小于60的学生
public class StudentTest {
private static List<Student> student = new ArrayList<>();
static {
student.add(new Student(Long.valueOf(1), "001", "小屁①号", "女", 100));
student.add(new Student(Long.valueOf(2), "002", "小屁②号", "男", 20));
student.add(new Student(Long.valueOf(3), "003", "小屁③号", "男", 90));
student.add(new Student(Long.valueOf(4), "004", "小屁④号", "女", 40));
student.add(new Student(Long.valueOf(5), "005", "小屁④号", "女", 70));
}
//需求:获取所有性别为男的学生
//传统方法
public static void main(String[] args) {
List<Student> stu = new ArrayList<>();
for (Student s : student
) {
if (s.getSex().equals("男")) {
stu.add(s);
}
}
System.out.println("性别为男的学生是:" + stu);
System.out.println("❀ ❀ ❀ ❀ ❀ ❀ ❀ 实现接口的方式 ❀ ❀ ❀ ❀ ❀ ❀ ❀");
findStudentSex(new Myprodicte() {
@Override
public boolean test(Student s) {
return s.getSex().equals("男");
}
});
System.out.println("❀ ❀ ❀ ❀ ❀ ❀ ❀Lambda 方式改造 ❀ ❀ ❀ ❀ ❀ ❀ ❀");
findStudentSex(s->s.getSex().equals("男"));
}
//根据定义的接口规则实现需求
public static void findStudentSex(Myprodicte my) {
List<Student> stu = new ArrayList<>();
for (Student stu1 : student
) {
if (my.test(stu1)) {
stu.add(stu1);
}
}
System.out.println("性别为男的学生:"+ stu);
}
}
//接口
package cn.wolfcode.annotation;
import cn.wolfcode.annotation.Student;
/**
* @author: 阿落
* @date: 2022/8/23 19:04
*/
public interface Myprodicte {
boolean test(Student s);
}
3.Lambda表达式的特点
- 可选类型声明:没有特殊要求不写参数类型,如果要求写,需要使用小括号将参数类型和参数括起来。
public class LambdaDemo {
public static void main(String[] args) {
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
list.forEach(list1 -> System.out.println(list1));
}
}
package cn.wolfcode.annotation;
import java.util.*;
/**
* @author: 阿落
* @date: 2022/8/23 20:30
*/
public class LambdaDemo {
public static void main(String[] args) {
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
list.forEach(list1 -> System.out.println(list1));
//①无参
new Thread(() -> System.out.println("开启多线程")).start();
//②一个参数
list.forEach(s -> System.out.println(s));
//③多个参数
Map<String, String> map = new HashMap<>();
map.put("1", "小屁①号");
map.put("2", "小屁②号");
map.put("3", "小屁③号");
map.forEach((k, v) -> System.out.println(k + "::" + v));
}
}
map.forEach((k,v)->{System.out.println(v);System.out.println(v);});
4.常见的函数式接口
既然Lamnda表达式能改造的必须是函数式接口,那么常见的函数式接口都有哪些类型呢?
- 消费型接口
- 供给型接口
- 函数型接口
- 断言型接口
函数式接口 | 参数类型 | 返回类型 | 说明 |
---|---|---|---|
Consumer(消费型接口) | T(只进不出) | void | 对类型为T的对象操作 方法:void accept(T t) |
supplier(供给型接口) | 无(只出不进) | T | 返回类型为T的对象 方法:T get();可用作工厂 |
Function<T,R>(函数型接口) | T(有进有出,出的类型是java中的任意类型) | R | 对类型为T的对象操作,并返回结果是R类型的对象 方法:R apply(T t); |
Predicate(断言型接口) | T(有进有出,出的类型是boolean型) | Boolean | 判断类型为T的对象是否满足条件,并返回boolean值 方法:boolean test(T t) |
5.演示案例
package cn.wolfcode.test;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.supplier;
/**
* @author: 阿落
* @date: 2022/8/23 22:45
*/
public class functionalInterfaceAPIDemo {
//需求①:编写shop方法输出消费多少元---消费型接口Consumer<T>
public void shop(int money, Consumer<Integer> consumer) {
consumer.accept(money);
}
//需求②:编写getCode方法返回指定位数的随机验证码字符串,使用供给型的函数式接口:supplier<T>(有进有出,出为任意类型)
public String getCode(int len, supplier<Integer> supplier) {
//定义StringBuilder类型SB用来拼接获取到的字符串
StringBuilder SB = new StringBuilder();
//根据用户传入的参数获取指定个数的字符
for (int i = 0; i <= len; i++) {
//调用函数型接口supplier中的get方法获取字符并拼接
SB.append(supplier.get());
}
//SB为StringBuilder类型,转为String类型
return SB.toString();
}
//需求③:编写getStringRealLength方法来获取字符串的真实长度
public int getStringRealLength(String str, Function<String, Integer> fun) {
return fun.apply(str);
}
//需求④:编写getString方法获取长度大于等于5的字符串。
public List<String> getString(List<String> list, Predicate<String> predicate) {
List<String> list1 = new ArrayList<>();
for (String str : list
) {
if (predicate.test(str)) {
list1.add(str);
}
}
return list1;
}
}
package cn.wolfcode.test;
import org.junit.Test;
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;
/**
* @author: 阿落
* @date: 2022/8/24 0:57
*/
public class functionalInterfaceAPIDemoTest {
functionalInterfaceAPIDemo fI = new functionalInterfaceAPIDemo();
@Test
public void shop() {
fI.shop(10000, new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println("昨晚落总共消费了" + integer + "元。");
}
});
//lambda改造
fI.shop(100000, integer -> System.out.println("昨晚落总共消费了" + integer + "元。"));
}
@Test
public void getCode() {
System.out.println(fI.getCode(6, new supplier<Integer>() {
@Override
public Integer get() {
return (int) (Math.random() * 10);
}
}
));
//lambda改造
System.out.println(fI.getCode(6, () -> (int) (Math.random() * 10)));
}
@Test
public void getStringRealLength() {
System.out.println(fI.getStringRealLength("小屁爱吃哈哈屁", new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return s.length();
}
}));
//lambda改造
System.out.println(fI.getStringRealLength("小屁爱吃哈哈屁", s -> s.length()));
}
@Test
public void getString() {
List<String> list = Arrays.asList("小屁", "小屁①号", "小屁爱吃屁", "小屁爱吃哈哈屁", "xiaopi");
System.out.println(fI.getString(list, new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length() >= 5;
}
}));
//lambda改造
System.out.println(fI.getString(list, s -> s.length() >= 5));
}
}
3.方法引用
@Test
public void getStringRealLength() {
System.out.println(fI.getStringRealLength("小屁爱吃哈哈屁", new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return s.length();
}
}));
//lambda改造
System.out.println(fI.getStringRealLength("小屁爱吃哈哈屁", s -> s.length()));
//方法引用
System.out.println(fI.getStringRealLength("xiaopi", String::length));
}
注意事项:
4.延迟加载
指java代码命令被执行,却因为不满足条件不输出的情况,造成了性能浪费,我们可以在代码执行前先判断,满足要求就执行,不满足就不执行。(举个例子,你现在是一家蛋糕店老板,你现在要给一位顾客做个巧克力蛋糕,如果你不知道他爱不爱吃,直接做好送过去了,顾客不喜欢不要,是不是就浪费了,但你如果提前问清楚她的口味,如果喜欢就做,不喜欢就不做,是不是就避免了浪费。)
package cn.wolfcode.test;
import java.util.function.supplier;
/**
* @author: 阿落
* @date: 2022/8/24 20:59
*/
public class LazyTest {
public static void main(String[] args) {
String name = "小屁";
String money = "100000元";
String action = "shopping";
isContinue("on", new supplier<String>() {
@Override
public String get() {
return name + "去" + action + "花了" + money;
}
});
}
public static void isContinue(String info, supplier<String> supplier) {
if (info.equalsIgnoreCase("on")) {
supplier.get();
System.out.println(supplier.get());
}
}
}
package cn.wolfcode.test;
import java.util.function.supplier;
/**
* @author: 阿落
* @date: 2022/8/24 20:59
*/
public class LazyTest {
public static void main(String[] args) {
String name = "小屁";
String money = "100000元";
String action = "shopping";
isContinue("s", new supplier<String>() {
@Override
public String get() {
return name + "去" + action + "花了" + money;
}
});
}
public static void isContinue(String info, supplier<String> supplier) {
if (info.equalsIgnoreCase("on")) {
supplier.get();
System.out.println(supplier.get());
}
}
}