zoukankan      html  css  js  c++  java
  • lambda表达式

    [原文地址为]https://www.cnblogs.com/haixiang/p/11029639.html#791844013

    定义

    lambda表达式是jdk1.8后新增的特性,它可以取代大部分匿名内部类,简化Java代码结构。
    lambda表达式是基于函数式接口使用的。
    什么是函数式接口?
    函数式接口是指只含有一个必须被重写的方法的接口。
    (注:只有一个必须重写的方法,并不是指只有一个方法,jdk1.8后接口中允许有已经实现的方法(必须被public static修饰),jdk1.8后也允许有非必须重写的抽象方法(须被default修饰))

    @FunctionalInterface

    函数式接口又称为功能性接口,故一般函数式接口都用@FunctionalInterface注解进行修饰。
    (不使用该注解,jvm虚拟机也可判断出该接口是一个函数式接口,但为了防止其他同事在该接口中新增方法,最好使用注解注明)

    lambda基础语法

    lambda基础语法一般是基于以下6种函数式接口

    //1.无返回无参数函数式接口
    @FunctionalInterface
    public interface noReturnNOParam{
      void method();
    }
    //2.无返回一参数函数式接口
    public interface noReturnOneParam{
      void method(int a);
    }
    //3.无返回多参数函数式接口
    public interface noReturnMultiParam{
      void method(int a,int b);
    }
    //4.有返回无参数函数式接口
    public interface ReturnNoParam{
      String method();
    }
    //5.有返回一参数函数式接口
    public interface ReturnOneParam{
      String method(int a);
    }
    //6.有返回多参数函数式接口
    public interface ReturnMultiParam{
      String method(int a,int b);
    }
    

    lambda表达式的基础语法为()->{},其中()中保存参数列表,->是lambda表达式的执行符,读作goes to,{}中保存方法体。
    关于lambda表达式,这里有一句口诀:
    上联:左右遇一括号省
    下联:左边类推类型省
    横批:能省则省
    解释
    左右遇一括号省
    左指的是若只有一个参数,则左边参数的括号可省略不写。
    右指的是若方法体中只有一条Java语句,则右边的括号也可省略不写。
    左边类推类型省:
    jvm虚拟机的类推机制,可通过方法体中的语句,联系上下文推测出参数列表的类型,因此左边的参数类型可省略不写。

    针对上述接口及口诀,下方有几个例子

    public class testLambda(){
      public static void main(String args[]){
      //1.无返回,无参数值
      noReturnNOParam emp1=()->{
          System.out.println("无返回无参数值");
        };
      emp1.method();//这里的method是上述函数式接口中定义的方法名
      //使用口诀简化版
      noReturnNoParam emp1=()-> System.out.println("无返回无参数值");
      emp1.method();
      //注意这边参数为0个,所以左边括号不能省 
      //============================================================
      //2.无返回,一参数值
      noReturnOneParam emp2=(String a)->{
        System.out.println("无返回,一参数值"+a);
      }; 
      emp2.method("11111");
      //简化版
      noReturnOneParam emp2=a->
      System.out.println("无返回,一参数值"+a);
      emp2.method("11111");
      //=============================================================
      //3.无返回,多参数值
      noReturnMultiParam emp3=(int a,int b)->{
        System.out.println("无返回,一参数值"+(a+b));
      };
      emp3.method(1,2);
      //简化版
      noReturnMultiParam emp3=(a,b)->System.out.println("无返回,多参数值"+(a+b));
      emp3.method(1,2);
      //======================================================================
      //4.有返回,无参数值
      ReturnNOParam emp4=()->{
          return "无返回无参数值";
        };
      String return1=emp4.method();//这里的method是上述函数式接口中定义的方法名
      //使用口诀简化版
      noReturnNoParam emp1=()->  return "无返回无参数值";
      String return1=emp4.method();
      //注意这边参数为0个,所以左边括号不能省 
      //============================================================
      //5.有返回,一参数值
      ReturnOneParam emp5=(String a)->{
        return "有返回,一参数值"+a;
      }; 
      String return2=emp5.method("11111");
      //简化版
      ReturnOneParam emp5=a->
      return "无返回,一参数值"+a;
      String return2=emp5.method("11111");
      //=============================================================
      //6.无返回,多参数值
      ReturnMultiParam emp6=(int a,int b)->{
        return "无返回,一参数值"+(a+b);
      };
      String return3=emp6.method(1,2);
      //简化版
      ReturnMultiParam emp6=(a,b)->return "无返回,多参数值"+(a+b);
      String return3=emp6.method(1,2);
     }
    }
    
    

    Lambda表达式常用方法示例

    lambda表达式引用方法

    可以利用lambda表达式的接口直接指向一个已经实现的方法
    要求:
    1.这个方法的参数类型及个数要与函数式接口中的方法一致
    2.这个方法的返回值类型要与函数式接口中的方法一致
    语法:
    方法名::方法的归属者,静态方法的归属者为类名,普通方法的归属者为对象
    举例:

    public class lambdaUse1{
      public static void main(String args[]){
        ReturnMultiParam return1=fangfa1::lambdaUse1;
        return1.method(1,2);
      }
      public static String fangfa1(int a,int b){
        int c=a+b;
        return "lambda表达式的用法1"+c;
      }
    }
    //就相当于用引用的方法重写了原接口中的方法,就是lambda表达式中的goes to到引用方法的方法体中
    

    构造方法的引用

    若一个函数式接口中的方法,是一个类的构造方法,则可通过lambda表达式来创建该类的对象,
    语法:类名::new

    //无参构造
    public Interface ItemCreaterConstruct(){
      Item getItem();
    }
    //含参构造
    public Interface ItemParamCreaterConstruct(){
      Item getItem(int id,String name,double price);
    }
    
    public class emp(){
      public static void main(String args[]){
        //无参构造,使用lambda表达式创建对象
        ItemCreaterConstruct construct=()->new Item();
        Item item=construct.getItem();
        //无参构造,使用lambda表达式的另一种写法创建对象
        ItemCreaterConstruct construct=Item::new;
        Item item=construct.getItem();
        //含参构造,使用lambda表达式创建对象
        ItemCreaterConstruct construct=Item::new;
        Item item=construct.getItem(1,"aaa",1.1);   
    }
    
    }
    

    lambda表达式创建线程

    我们以往创建线程都是通过继承Thread后重写run方法,通过lambda表达式可以简化线程的创建过程

    //这里是通过Thread的一个构造方法   
    public Thread(Runnable target) {
            init(null, target, "Thread-" + nextThreadNum(), 0);
        }
    //来创建线程
    //Runnable接口中只有一个run方法,则可通过lambda表达式来代替构造方法中的Runnable
    Thread t=new Thread(()->{
      for(int i=0;i<10;i++){
      System.out.println(i)
    }
    });
    t.start();
    

    遍历集合

    我们可以调用集合中的public void forEach(Consumer <? Super E> action)方法,通过lambda表达式的方式遍历集合中的元素。
    Consumer是JDK给我们提供的一个函数式接口。

    @FunctionalInterface
    public interface Consumer<T>{
      void acctept(T t);
    }
    List list=new ArraysList();
    list.forEach(element->{ 
        if(element.get(i)%2==0){
        System.out.println(""+element);
    }
    });
    
    

    删除集合中的元素

    我们可以通过public boolean removeIf(Predicate<? super E> filter)方法来删除集合中的某个元素,Predicate也是JDK提供的一个函数式接口。

     ArrayList<Item> items = new ArrayList<>();
          items.add(new Item(11, "小牙刷", 12.05 ));
          items.add(new Item(5, "日本马桶盖", 999.05 ));
          items.add(new Item(7, "格力空调", 888.88 ));
          items.add(new Item(17, "肥皂", 2.00 ));
          items.add(new Item(9, "冰箱", 4200.00 ));
    
          items.removeIf(ele -> ele.getId() == 7);
    
          //通过 foreach 遍历,查看是否已经删除
          items.forEach(System.out::println);
    

    集合内元素的排序

    在以前我们要为集合内的元素进行排序,就必须要用sort方法,传入比较器匿名内部类重写Compare方法,我们现在可以使用lambda表达式来简化代码

    ArrayList<Item> list = new ArrayList<>();
            list.add(new Item(13, "背心", 7.80));
            list.add(new Item(11, "半袖", 37.80));
            list.add(new Item(14, "风衣", 139.80));
            list.add(new Item(12, "秋裤", 55.33));
    
            /*
            list.sort(new Comparator<Item>() {
                @Override
                public int compare(Item o1, Item o2) {
                    return o1.getId()  - o2.getId();
                }
            });
            */
    
            list.sort((o1, o2) -> o1.getId() - o2.getId());
    
            System.out.println(list);
    

    lambda表达式的闭包问题

    这个问题在匿名内部类也存在,若我们放开注释则会报错,这里num我们虽然没有添加final注释,但是虚拟机在编译时会自动给其添加一个final修饰关键字。

    import java.util.function.Consumer;
    public class Main {
        public static void main(String[] args) {
    
            int num = 10;
    
            Consumer<String> consumer = ele -> {
                System.out.println(num);
            };
    
            //num = num + 2;
            consumer.accept("hello");
        }
    }
    
  • 相关阅读:
    ElasticSearch原理
    redis master配置了密码进行主从同步
    redis sentinel 高可用(HA)方案部署,及python应用示例
    Linux Redis集群搭建与集群客户端实现
    字符串倒序
    单链表反转
    【python】面试常考数据结构算法
    面试中的排序算法总结
    Memcached 真的过时了吗?
    Activity生命周期
  • 原文地址:https://www.cnblogs.com/planted/p/15168166.html
Copyright © 2011-2022 走看看