lambda的一点高级用法

651 阅读3分钟

这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战

lambda表达式类型推断

在 lambda的方法引用一文中juejin.cn/post/699999… 已经说明了 lambda是个匿名方法,最后返回一个实现了指定接口的对象,所以你就要说明实现的是哪个接口,否则会报错这就是类型推断

类型推断有多种方式



@FunctionalInterface
interface IMath{
    int add(int x,int y);
}
public class TypeDemo {
    public static void main(String[] args) {

        //变量类型定义
        IMath lambda = (x,y)->x+y;

        //数组里
        IMath[]lambdas = {(x,y)->x+y};

        //强制类型转换
        Object lambda2 = (IMath)(x,y)->x+y;

        //通过返回类型
        IMath createLambda =createLambda();

        TypeDemo demo = new TypeDemo();

       
        demo.test((x, y) -> x+y);
    }

    
    public void test(IMath math){

    }

}

以上就是一般来说的方式

在IMath下新建一个接口IMath2

@FunctionalInterface
interface IMath2{
    int sub(int x,int y);
}

重载一下 test

public void test(IMath math){

}
public void test(IMath2 math){

}

此时发现了一个问题

image.png

重载了 test引发的时候确不指出是哪个,所以报了错 这样的时候我们就要指定类型

//当不确定性的时候,使用强制类型转换
demo.test((IMath2) (x, y) -> x+y);

lambda表达式变量引用、

既然lambda是匿名类,那么引用过程和 匿名类是同样的。 先看代码

public class VarDemo {
    public static void main(String[] args) {
        String str = "这个string不可以在修改";
        str = "44944";
        Consumer<String> consumer = s-> System.out.println(s+str);
        consumer.accept("1211");
    }

}

image.png 为什么这个str 不可以修改呢 ? 有些用过java 8以前的版本的大佬应该知道从前匿名类引用外面的对象要加上 final ,但是java8默认给你加上了,所以这里不写 final 也无所谓

那我们就不理解了,为什么要加上 final

首先想个问题 Java传参数是传值,还是传引用? 答案是传值。 我们再看看另一坨代码

List<String> list = new ArrayList<>();    //list 记作 A   
Consumer<String> consumer2 = s-> System.out.println(s+list);
consumer2.accept("1234");

image.png

当代码这么写,就更容易解释为什么是值引用,就会导致不可修改 上面 list 在 C 处调用 的过程中, A -> B -> C 如果值改变了, 也就是说 A -> D ,但是此时因为是值引用,导致 B ->C
同样调用一个 list 却得出了不同的值。

如果是传引用 那么就是 C -> B -> A ,A怎么换都无所谓

级联表达式 柯里化

什么是级联表达式?

级联表达式是多个箭头的表达式 x->y -> x+ y

以上的表达式代表什么意思呢? lambda表达式 左面是输入右边是输出。 先看第一个-> ,输入了 x 输出了 y->x+y;所以这是个 Function 第二个 -> ,输入了 y 输出了 x+y ,所以这也是个 Function 最后 是个 x+ y ,所以可能是 数字或字符串,我们先当作 数字

public static void main(String[] args) {
   Function<Integer,Function<Integer,Integer>>function =  x->y ->x+y;
    System.out.println(function.apply(2).apply(3));
}

image.png

柯里化:把多个参数的函数转换为只有一个参数的函数 柯里化的意义:把函数标准化 高阶函数:返回函数的函数

柯里化之前

Function<Integer,Function<Integer,Function<Integer,Integer>>> fun2 = x->y->z -> x+y+z;

System.out.println(fun2.apply(2).apply(3).apply(4));

那岂不是越来越多的函数就代表越来越长

柯里化之后。。。

Function f = fun2;
for (int i=0;i<nums.length;i++){
    if (f instanceof Function){
        Object obj = f.apply(nums[i]);
        if (obj instanceof Function){
            f = (Function) obj; 
        }else {
            System.out.println("调用结束:结果为"+obj);
        }
    }
}

调用的是一个函数,返回的依旧是要给函数。