美文网首页
lambda快速入门

lambda快速入门

作者: 深圳邱道长 | 来源:发表于2020-02-25 21:26 被阅读0次

    视频:https://www.bilibili.com/video/av91634578/

    lambda是什么?

    匿名函数。是一种函数式编程的风格。

    • 函数式编程强调是做什么。不强调怎么做。

    lambda可以作为值传递

    匿名函数,匿名方法差不多。

    方法怎么写。

    lambda语法

    (参数列表) -> {代码逻辑}

    一个参数使用

    package com.github.qiudaozhang;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    
    interface  OneParam{
    
        void show(int i);
    }
    
    public class OneParamDemo {
    
        public static void main(String[] args) {
            // lambda它能够类型推断,知道你这里面是一个int 类型的数据。
            OneParam oneParam = (i) -> {
                System.out.println(i * 2);
            };
            oneParam.show(3);
        }
    }
    
    

    两个参数还有返回值

    package com.github.qiudaozhang;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    
    interface SumInterface{
        int sum(int x ,int y);
    }
    
    public class SumMain {
    
        public static void main(String[] args) {
            SumInterface sumInterface = (x,y) -> {return x + y;};
            int sum = sumInterface.sum(3, 5);
            System.out.println(sum);
        }
    }
    
    

    省略{}情况

    如果其逻辑只有一个语句,可以省略{}

    package com.github.qiudaozhang;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    
    interface  OneParam{
    
        void show(int i);
    }
    
    public class OneParamDemo {
    
        public static void main(String[] args) {
            OneParam oneParam = (i) -> System.out.println(i*2);
            oneParam.show(3);
        }
    }
    
    

    省略()情况

    如果只有一个参数,那么这个括号也可以省略

    package com.github.qiudaozhang;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    
    interface  OneParam{
    
        void show(int i);
    }
    
    public class OneParamDemo {
        public static void main(String[] args) {
    
            OneParam oneParam = i -> System.out.println(i*2);
            oneParam.show(3);
        }
    }
    
    

    省略return情况

    下面的写法是错误的。

    package com.github.qiudaozhang;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    
    interface SumInterface{
        int sum(int x ,int y);
    }
    
    public class SumMain {
    
        public static void main(String[] args) {
            SumInterface sumInterface = (x,y) -> return x + y;
            int sum = sumInterface.sum(3, 5);
            System.out.println(sum);
        }
    }
    
    

    下面的省略了return是正确的。

    package com.github.qiudaozhang;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    
    interface SumInterface{
        int sum(int x ,int y);
    }
    
    public class SumMain {
    
        public static void main(String[] args) {
            SumInterface sumInterface = (x,y) ->  x + y;
            int sum = sumInterface.sum(3, 5);
            System.out.println(sum);
        }
    }
    
    

    为什么它这么聪明?

    推断。

    写的接口都是函数式接口。

    只有一个抽象方法的接口就是函数式接口。

    我们下面这么玩就不行,无法唯一确定。

    package com.github.qiudaozhang;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    interface  NoGood{
        void good(int x);
        
        void bad(int y);
    }
    
    public class NoGoodDemo {
    
        public static void main(String[] args) {
            NoGood n = (x) -> {};
        }
    }
    
    

    应该使用函数式接口注解标记

    @FunctionalInterface
    interface  NoGood{
    //    void good(int x);
    
        void bad(int y);
    }
    

    此时编译器就能够检查。

    如果定义了多个方法真的不行吗?

    下面的是允许的

    @FunctionalInterface
    interface  NoGood{
        void good(int x);
    
        String toString();
    }
    

    默认实现。

    克隆集合,null元素不要。

    package com.github.qiudaozhang;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    public class OldStyleNonEle {
    
        public static void main(String[] args) {
            List<String> l = Arrays.asList("james",null,"bosh",null,"wade");
            List<String> strings = nonNull(l);
            System.out.println(strings);
        }
        public static List<String> nonNull (List<String> l) {
            List<String> result = new ArrayList<>();
    
            for(String s:l) {
                if(s != null) {
                    result.add(s);
                }
            }
    
            return result;
        }
    }
    
    

    lambda风格实现。

    package com.github.qiudaozhang;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    public class LambdaStyleNonEle {
    
        public static void main(String[] args) {
            List<String> l = Arrays.asList("james",null,"bosh",null,"wade");
            List<String> strings = nonNull(l);
            System.out.println(strings);
        }
    
        public static  List<String> nonNull(List<String> l) {
            List<String> result = new ArrayList<>(l);
            result.removeIf(it -> it == null);// 最终以布尔类型取决
            // 传入一个谓词,是不是。
            return result;
        }
    }
    
    

    removeIf必然默默的走了循环。

    方法引用

    lambda里面可以使用 ::引用法。

    • 实例方法引用 实例::方法名
    • 静态方法引用 类名::方法名
    • 构造方法引用类名::new

    实例引用

    package com.github.qiudaozhang;
    
    import java.util.function.Consumer;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    public class ConsumerDemo {
    
        public static void main(String[] args) {
    //
    //        Consumer consumer = (it) -> {
    //            System.out.println(it);
    //        };
    //        consumer.accept("love");
            Consumer consumer = System.out::println;
            consumer.accept("love");
    
        }
    }
    
    

    静态引用

    package com.github.qiudaozhang;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    
    interface  StaticRef{
        void show();
    }
    public class StaticRefMain {
    
    
        public static void main(String[] args) {
            StaticRef staticRef = StaticRefMain::myShow;
            staticRef.show();
        }
    
        public static void myShow() {
            System.out.println("爱老婆很好");
        }
    }
    
    

    构造引用

    package com.github.qiudaozhang;
    
    import java.util.function.Supplier;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    
    class User{
        String name;
        String age;
    
    
        public User() {
            System.out.println("我是构造方法哦");
        }
    }
    
    public class SupplierMain {
    
        public static void main(String[] args) {
    
    //        Supplier supplier = () -> new Object();
            Supplier<User> supplier = User::new;
            User user = supplier.get();
        }
    }
    
    

    Consumer

    package com.github.qiudaozhang;
    
    import java.util.function.Consumer;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    public class ConsumerDemo {
    
        public static void main(String[] args) {
    
            Consumer consumer = (it) -> {
                System.out.println(it);
            };
            consumer.accept("love");
    
        }
    }
    
    

    对于处理参数没有过多额外逻辑情况下,可以用方法引用,参数都可以不写。

    自我推断。

    Supplier

    package com.github.qiudaozhang;
    
    import java.util.function.Supplier;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    public class SupplierMain {
    
        public static void main(String[] args) {
            
            Supplier supplier = () -> new Object();
        }
    }
    
    

    ToIntFunction

    package com.github.qiudaozhang;
    
    import java.util.function.ToIntBiFunction;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    public class ToIntFunctionMain {
    
        public static void main(String[] args) {
            ToIntBiFunction<String,String> toIntBiFunction = (x,y) -> Integer.parseInt(x) + Integer.parseInt(y);
            int i = toIntBiFunction.applyAsInt("37", "77");
            System.out.println(i);
        }
    }
    
    

    参数类型不能省略情况

    package com.github.qiudaozhang;
    
    import java.util.function.Consumer;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    public class ParamTypeNeed {
    
        public static void main(String[] args) {
            show("ss",t -> {
                System.out.println(t);
            });
        }
    
    
        public static void show(CharSequence s , Consumer<CharSequence> consumer) {
            System.out.println(1);
            consumer.accept(s);
        }
    
        public static void show(String s , Consumer<String> consumer) {
            System.out.println(2);
            consumer.accept(s);
        }
    
    }
    
    
    package com.github.qiudaozhang;
    
    import java.util.function.Consumer;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    public class ParamTypeNeed {
    
        public static void main(String[] args) {
            show("ss",(CharSequence t) -> {
                System.out.println(t);
            });
        }
    
    
        public static void show(CharSequence s , Consumer<CharSequence> consumer) {
            System.out.println(1);
            consumer.accept(s);
        }
    
        public static void show(String s , Consumer<String> consumer) {
            System.out.println(2);
            consumer.accept(s);
        }
    
    }
    
    

    或者

    package com.github.qiudaozhang;
    
    import java.util.function.Consumer;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    public class ParamTypeNeed {
    
        public static void main(String[] args) {
            show("ss",(String t) -> {
                System.out.println(t);
            });
        }
    
    
        public static void show(CharSequence s , Consumer<CharSequence> consumer) {
            System.out.println(1);
            consumer.accept(s);
        }
    
        public static void show(String s , Consumer<String> consumer) {
            System.out.println(2);
            consumer.accept(s);
        }
    
    }
    
    

    java 闭包

    Java的闭包比JS肯定要弱的,Java只能部分实现闭包的概念。考虑现实的问题。折中方案来适应开发需求。

    未来

    • oop基石
    • 配合函数式编程风格辅助

    lambda和内部类

    不是一回事。

    • lambda里面不能访问非常量。
    package com.github.qiudaozhang;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    
    
    public class LambdaCanAccess {
    
        public static void main(String[] args) {
    
            int a = 3;
            a = 4;
            Greeting g = () -> {
                System.out.println(a);//错误,不能访问
            };
        }
    }
    
    

    下面的写法还是不行的。

    package com.github.qiudaozhang;
    
    /**
     * 邱道长
     * 2020/2/25
     */
    
    
    public class LambdaCanAccess {
    
        public static void main(String[] args) {
    
            int a = 3;
            Greeting g = () -> {
                System.out.println(a);
            };
            a = 4;
        }
    }
    
    
    • lambda没有自己的this,内部类是有的
    • lambda仅仅是方法级别,内部类是类级别
    • 内部类可以继承其它类,还可以实现很多接口,lambda只能搞一个函数式接口
    • 内部类也是有class文件的,lambda最终只是外部类的一个私有方法
    • 内部类jar会大一些,lambda会小一些

    有的功能是必须要用内部类。

    缺点

    • 调试来讲灾难,导致堆栈很长,javac支持较好,JVM层面。
    • 你必须要适应函数式编程风格。

    相关文章

      网友评论

          本文标题:lambda快速入门

          本文链接:https://www.haomeiwen.com/subject/oluqchtx.html