zoukankan      html  css  js  c++  java
  • (三)lamda

    lambda

    lambda可以理解为匿名函数,由参数列表 箭头 函数主体组成
    语法

    (parameters)->expression 或 (parameters)->{statements;}
    

    第一种只有一句表达式,会默认返回表达式的值,所以隐藏了return。例如

    (Integer x)-> x+x
    

    第二种用于有多个表达式逻辑的代码块,必须使用return明确返回值。

    (Integer x)-> {
                System.out.println("start ++x");
                ++x;
                return x;
            };
    

    函数接口

    函数接口是仅有一个抽象方法的接口,例如Function接口

    @FunctionalInterface
    public interface Function<T, R> {
        R apply(T t);
    }
    

    函数接口的作用是可以让lambda表达式为函数式接口的抽象方法提供实现,用lambda直接取代内部类
    比如runnable内部类接口

    Runnable r2 = new Runnable(){
    	public void run(){
    		System.out.println("Hello World 1");
    	}
    };
    

    Runnable 的lambda方式

    Runnable r1 = () -> System.out.println("Hello World 1");
    
    

    这两种方式完全等价,可以说离开函数接口,lambda表达式没有任何作用,一个lambda函数始终是函数接口的实现。

    类型推断

    lambda表达式可以在编辑期间自动推断参数类型
    例如

     Function<Integer,Integer> fs = (x)-> x+x;
    

    该例子可以通过Function接口的泛型化参数推断出x是Integer类型的参数。

    初学者如何写好lambda表达式

    熟悉相关函数接口,明确函数接口抽象方法的结构(参数列表和返回值类型)
    例如Function接口

    @FunctionalInterface
    public interface Function<T, R> {
        R apply(T t);
    }
    

    观察抽象方法 R apply(T t);可见该抽象方法定义为由一个T类型的值返回一个R类型的返回值
    例如

    Function<Integer,String> fs = (x)-> {
              String helloString = "hello" + x.intValue();
              return helloString;
           };
    

    声明为输入参数T为Integer类型,返回值R为String类型,所以lambda的参数列表数目(lambda参数可以自动推断)和函数接口抽象方法数目一致,lambda方法体返回结果类型和函数接口返回值类型一致即可。

    方法引用

    ClassName::staticMethod或者ClassName::instanceMethod
    静态方法的引用

    public class Main {
    
        public static void main(String[] args) {
            List<String> strings = new ArrayList<>();
            strings.forEach(Main::print);
        }
        public static void print(String abc){
            System.out.println(abc);
        }
    }
    

    需要注意的是所引用的方法需要和相关的函数接口匹配(和函数接口的参数类型和返回值一致),比如这个例子的forEach方法接受的函数接口是Consumer

        default void forEach(Consumer<? super T> action) {
            Objects.requireNonNull(action);
            for (T t : this) {
                action.accept(t);
            }
        }
    

    Consumer是一个消费型的函数接口,接受一个T类型,无返回值

    @FunctionalInterface
    public interface Consumer<T> {
        void accept(T t);
    }
    

    而我们的print方法接受一个String类型的参数,无返回值,且strings被限定为String类型,所以Consumer的T类型是String类型,因此print方法能和Consumer函数接口匹配。
    实例方法引用

            List<String> list = new ArrayList<>();
            list.stream().sorted(String::compareTo);
    

    静态方法引用与实例方法引用的区别

    静态方法
    ClassName::staticMethod ==== (x)->{statements}
    实例方法引用
    ClassName::staticMethod ==== (x,y)->{statements}
    instanceObject::instanceMethod ===== (x)->{statements}
    关注公众号,一起阅读IT经典书籍

    关注公众号,一起阅读经典书籍

  • 相关阅读:
    「2019.7.25 考试」偶然发生
    「刷题」可怜与STS
    「刷题」小星星
    「刷题」数三角形
    「刷题」 关于线段上的整点个数
    「刷题」Color 群论
    「2019.7.22 考试」AC和WA0一步之遥
    「刷题」幸运数字
    「刷题」卡特兰数&prufer序列
    「刷题」一个人的数论
  • 原文地址:https://www.cnblogs.com/vincili/p/9265984.html
Copyright © 2011-2022 走看看