函数式接口
函数式接口:
有且仅有一个抽象方法的接口(可以有其他方法)
@FunctionalInterface注解:
和Override用法基本相同,此注解可以用于任何接口,表示函数式接口,加了注解编译器会自动检是否有且仅有一个抽象函数。不加注解满足函数式接口的条件也是函数式接口
自定义函数式接口:
@FunctionalInterface
interface IB {
int sub(int a,int b);
}
public class 有参有返回值 {
public static void main(String[] args) {
fun(new IB() {
@Override
public int sub(int a,int b) {
System.out.println("有参有返回值-匿名内部类");
return a + b;
}
},10,20);
fun((a,b)->{
System.out.println("有参有返回值-lambda表达式");
return a + b;
},10,20);
}
public static void fun(IB ib,int x,int y) {
System.out.println(ib.sub(x, y));
}
}
函数式编程
Lambda的应用_执行延迟:
计算完数据再去判断是否执行和先判断是否执行再计算数据,如果先计算就会浪费资源,
让计算的部分先交给接口,然后判断条件,如果满足在进行计算。
@FunctionalInterface
interface IA {
String s();
}
public class 执行延迟 {
public static void main(String[] args) {
String s1 = "我";
String s2 = "爱";
String s3 = "你";
fun(2,()->s1 + s2 + s3);
}
public static void fun(int level,IA ia) {
if (level == 1) {
System.out.println(ia.s());
}
}
}
Lambda的应用_作为参数和返回值:
@FunctionalInterface
interface IC{
void show();
}
public class 作为返回值 {
public static void main(String[] args) {
fun1(()-> System.out.println("作为参数"));
fun2().show();
}
//作为参数
public static void fun1(IC ic) {
ic.show();
}
//作为返回值
public static IC fun2() {
return () -> System.out.println("作为返回值");
}
}
方法引用
所谓“方法引用”就是:使用现有的方法,来代替实现的Lambda。
替代规则:
“替代的方法”的形参、返回值类型,必须与被替换的"函数式接口”中抽象
方法的一致。
静态方法替代Lambda:
可以是自定义静态方法,也可以是类库中的静态方法,只要这个静态方法和函数式接口中的抽象方法一样,(参数和返回值类型一致)就可以替代,语法 ::(双冒号)
@FunctionalInterface
interface IA{
void show();
}
public class 自定义方法替代Lambda {
public static void main(String[] args) {
//使用Lambda表达式
fun(()-> System.out.println("使用Lambda表达式"));
//使用自定义方法替代Lambda表达式
fun(自定义方法替代Lambda::s);
}
public static void fun(IA ia) {
ia.show();
}
public static void s() {
System.out.println("自定义静态方法替代Lambda");
}
}
对象成员方法替代:
首先创建对象,替换格式 对象名::方法名。返回值类型和参数一致
使用this本类方法:
@FunctionalInterface
interface Game{
public void run();
}
class Student{
public void playGame(Game game) {
System.out.println("我开始打游戏:");
game.run();
}
public void show(){
// playGame(() -> System.out.println("我喜欢打羽毛球...."));
playGame(this::ymq);
}
public void ymq(){
System.out.println("我喜欢打羽毛球....");
}
}
public class Demo {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
}
}
使用super父类方法:
要有继承关系
@FunctionalInterface
interface Game{
public void run();
}
class Fu{
public void like(){
System.out.println("我喜欢喝啤酒(我是父亲)....");
}
}
class Student extends Fu{
public void playGame(Game game) {
System.out.println("我开始打游戏:");
game.run();
}
public void show(){
//1.使用Lambda
playGame(() -> System.out.println("我喜欢喝啤酒...."));
//2.使用父类的like方法代替Lambda表达式
playGame(super::like);//使用父类的like方法代替Lambda表达式
}
}
public class Demo {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
}
}
类的构造器引用:
@FunctionalInterface
interface ID {
Cat getCat();
}
interface IE{
Cat getCat(String name);
}
class Cat {
public String name;
public Cat() {
}
public Cat(String name) {
this.name = name;
}
public void eat() {
System.out.println("小猫吃鱼");
}
public void pao() {
System.out.println(name+"在跑");
}
}
public class 类的构造器引用 {
public static void main(String[] args) {
//Lambda表达式
fun(() -> new Cat());
//类的构造器替代(无参)
fun(Cat::new);
//类的构造器替代(有参)
fun2(Cat::new,"大花猫");
}
public static void fun(ID id) {
id.getCat().eat();
}
public static void fun2(IE ie,String name) {
ie.getCat(name).pao();
}
}
数组构造器引用:
@FunctionalInterface
interface IA{
public int[] getArr(int len);
}
public class Demo {
public static void main(String[] args) {
//2.使用Lambda
fun((int len)->{return new int[len];},10);
//3.使用数组的构造器代替:Lambda
fun(int[]::new,15);
}
public static void fun(IA a,int len){
int[] arr = a.getArr(len);
System.out.println(arr.length);
}
}
常用函数式接口;
生产者接口_Supplier接口
1).生产者结果:只生产数据,不接收参数
public static void main(String[] args) {
fun1(()->10);
fun2(()->"hello");
}
public static void fun1(Supplier<Integer> ia) {
Integer a = ia.get();
System.out.println(a);
}
public static void fun2(Supplier<String> is) {
String s = is.get();
System.out.println(s);
}
消费者接口_Consumer接口_抽象方法accept
1).消费接口,只接受参数,无返回值;
public static void main(String[] args) {
fun((String s)-> System.out.println(s),"hello");
}
public static void fun(Consumer<String> cs,String s) {
cs.accept(s);
}
Consumer接口_默认方法andThen
作用:将两个Consumer对象的accept()方法的结果连在一起
源码:
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
例子:消费一个数据的时候,先调用第一个参数的accept,然后调用第二个参数的accept
实现两个组合
public static void main(String[] args) {
fun((String s)-> System.out.println("第一个:"+s),(String s)-> System.out.println("第二个:"+s),"hello");
}
public static void fun(Consumer<String> cs1, Consumer<String> cs2, String s) {
cs1.andThen(cs2).accept(s);
}
andThen返回一个Consumer类型, 重写的accept方法的方法体是
accept(t); after.accept(t);,先调用第一个accept再调用第二个accept,对应的就是方法调用处的第一个参数和第二个参数,也就是执行两个Consumer对象重写的accept方法