• java8 (jdk 1.8) 新特性——Lambda


    java8 (jdk 1.8) 新特性 ——初步认识 

     

    1. 什么是lambda?

    目前已知的是,有个箭头  ->  

    说一大段官方话,也没有任何意义

    我们直接看代码:

    之前我们创建线程是这样的

    复制代码
    Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println("run。。。。。。");
                }
            };
            runnable.run();
    复制代码

    用lambda:

    1
    2
    Runnable run2 = () -> System.out.println("run。。。。。。");
        run2.run();

      

     

     

     

    是不是感觉特别离谱,看不懂

    别急,还有更离谱的

    很常见的一个例子,比较两个整数的大小

    之前是这样写的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        Comparator myCom = new Comparator() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1, o2);
            }
        };
     
        int compare = myCom.compare(12, 20);
        int compare1 = myCom.compare(20, 12);
        int compare2 = myCom.compare(20, 20);
        System.out.println(compare);
        System.out.println(compare1);
        System.out.println(compare2);
    }

      

    用lambda:

    1
    2
    3
    4
    5
    6
    7
    8
    Comparator myCom = (o1, o2) -> Integer.compare(o1, o2);
     
    int compare = myCom.compare(12, 20);
    int compare1 = myCom.compare(20, 12);
    int compare2 = myCom.compare(20, 20);
    System.out.println(compare);
    System.out.println(compare1);
    System.out.println(compare2);

      甚至还可以这样 (这个是方法引用)

    1
    2
    3
    4
    5
    6
    7
    8
    Comparator myCom = Integer::compare;
     
           int compare = myCom.compare(12, 20);
           int compare1 = myCom.compare(20, 12);
           int compare2 = myCom.compare(20, 20);
           System.out.println(compare);
           System.out.println(compare1);
           System.out.println(compare2);

      

    第一个数比第二个数    

    大 :返回 1

    小:返回 -1

    相等:返回 0 

     

     

     

    刚接触是不是黑人问号,这是什么玩意 

    很好,到这,你认识到了lambda 一个缺点,可阅读性差 ,优点 代码简洁

    小结:看到 -> lambda           看到 : : 方法引用

     

    2.  lamdba 语法

     

     

    • 基本语法 

     1.  箭头操作符  ->  或者叫做lambda 操作符

     2.  箭头操作符将lambda 表达式拆分成两部分 

          左侧:Lambda 表达式的参数列表 

          右侧:Lambda 表达式中所需执行的功能  , 即 Lambda 体

     

     

    3. 语法格式

     

    语法格式1:无参数,无返回值 

    • 1
      () -> system.out.println("Hello Lambda")  

        

      前边线程的那个例子就是

     

    语法格式2:有一个参数 无返回值

    1
    (x)-> System.out.println(x);

      

    若只有一个参数可以省略不写

     

     

    1
    x-> System.out.println(x);

      

     之前的写法,没有使用lambda

    1
    2
    3
    4
    5
    6
    7
    8
    Consumer consumer = new Consumer() {
               @Override
               public void accept(String s) {
                   System.out.println("输出的值:"+s);
               }
           };
            
           consumer.accept("今天不想emo了");

      

     使用lambda 

    1
    2
    3
    Consumer consumer = s -> System.out.println("输出的值:"+s);
     
           consumer.accept("今天不想emo了");

     

    语法格式3:有两个以上参数 ,并且lambda体有多条语句,有返回值

    1
    2
    3
    4
    Comparator myCom = (o1, o2) -> {
             System.out.println("其他语句");
             return Integer.compare(o1, o2);
         };

      

    语法格式4  lambda体中只有一条语句,return 和 大括号都可以省略不写

    1
    Comparator com  =(x,y)-> Integer.compare(x,y);

      有没有发现所有的参数,都没有参数类型,之前我们写函数的时候可是要带上参数类型的

     

    语法格式5  lambda表达式参数列表的数据类型可以省略不写,因为JVM编译器通过上下文编译推断出数据类型——类型推断 

     

     

     4. 函数式接口

    不管上面哪一种语法格式,lambda都是需要函数式接口的支持

     函数式接口:接口中只有一个抽象方法的接口 称为函数式接口

    可以使用一个注解@FunctionalInterface 修饰,可以检查是否是函数式接口

    我们可以看看Runnable  接口 的源码

    完成的接口类代码如下

     

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    /*
     * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
     *  ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms
     /
     
    package java.lang;
    /**
     * The Runnable interface should be implemented by any
     * class whose instances are intended to be executed by a thread. The
     * class must define a method of no arguments called run.
     *

     * This interface is designed to provide a common protocol for objects that
     * wish to execute code while they are active. For example,
     * Runnable is implemented by class Thread.
     * Being active simply means that a thread has been started and has not
     * yet been stopped.
     *

     * In addition, Runnable provides the means for a class to be
     * active while not subclassing Thread. A class that implements
     * Runnable can run without subclassing Thread
     * by instantiating a Thread instance and passing itself in
     * as the target.  In most cases, the Runnable interface should
     * be used if you are only planning to override the run()
     * method and no other Thread methods.
     * This is important because classes should not be subclassed
     * unless the programmer intends on modifying or enhancing the fundamental
     * behavior of the class.
     *
     * @author  Arthur van Hoff
     * @see     java.lang.Thread
     * @see     java.util.concurrent.Callable
     * @since   JDK1.0
     */
    @FunctionalInterface
    public interface Runnable {
        /**
         * When an object implementing interface Runnable is used
         * to create a thread, starting the thread causes the object's
         * run method to be called in that separately executing
         * thread.
         *

         * The general contract of the method run is that it may
         * take any action whatsoever.
         *
         * @see     java.lang.Thread#run()
         */
        public abstract void run();
    }

      

     

     

     

     

     

    可以看到这里面就只有一个实现,有一个注解@FunctionalInterface ,说明它就是一个函数式接口,就可以进行lambda简写

     

    来看 Comparator 也是一样 有@FunctionalInterface注解

     

     

     

     

     

     

     

     

     

    这里可能就会有疑问,这边明明是有两个抽象方法,怎么是函数式接口呢?

     

    别急 !!可以看到这边的注释, 说明这个equals 是 重写了超类 的 equals,本质上是对object 的重写,官方定义这样的抽象方法是不会被定义到 抽象接口数的 ,因此实际上只有一个抽象方法

     

     

     

     

     

     我们自己可以试着定义 函数式接口,很简单

     

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    package com.test1.demo;
     
     
    @FunctionalInterface
    public interface MyFunc {
     
        void  method();
         
    }

      

     

     好了,如果,写两个抽象接口会怎样?

     

     

     

     

     

    可以看到注解报错了,所以注解用来校验作用就在这

     

     重申一遍,函数式接口:接口中只有一个抽象方法的接口 称为函数式接口

    注解只是拿来校验的,方便我们一看就知道这是一函数式接口类,不然还得数个数,验证一下是不是只有一个

     

     现在我也重写 equals ,可以看到并没有报错

     

     

     

     5. java8 中内置四大核心函数式接口 

    •   Consumer 消费型接口 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //Consumer  消费型接口
       @Test
       public void testConsumer() {
           cosumer(1000, (m) -> System.out.println("星期一" + m));
           // 星期一1000.0
       }
     
       public void cosumer(double m, Consumer con) {
           con.accept(m);
       }

      

     

    •  供给型接口  supplier

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @Test
        public void testSupplier() {
            List numList = getNumList(10, () -> (int) (Math.random() * 100));
            for (Integer integer : numList) {
                System.out.println(integer); //100 以内10位随机整数
            }
        }
     
        // 需求:产生指定个数的整数放入集合中
        public List getNumList(int num, Supplier su) {
            List list = new ArrayList<>();
            for (int i = 0; i < num; i++) {
                Integer integer = su.get();
                list.add(integer);
            }
            return list;
        }

      

     

    •  Function 函数型接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Test
       public void  FunctioStr(){
           String c = getFunction("sbjikss", str -> str.toUpperCase());
           System.out.println(c); //SBJIKSS
           String sub = getFunction("sbjikss", str -> str.substring(2, 3));
           System.out.println(sub);//j
       }
     
       public  String  getFunction( String str, Function f) {
           return f.apply(str);
       }

      

     

    • 断言型接口 Predicate  

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public  void  tetPre(){
            List list = Arrays.asList("Hello","sss","xxxx","sjjss");
           List list1 = filterStr(list, (pre) -> pre.length() > 3);
           for (String s : list1) {
               System.out.println(s);  // Hello xxxx  sjjss
           }
       }
      //需求:将满足条件字符串放入集合中
       public  List  filterStr(List old , Predicate pre ){
           List newList  = new  ArrayList<>();
           for (String str : old) {
               if (pre.test(str)){
                  newList.add(str);
               }
           }
           return newList;
       }

      

     感谢阅读!!!

     

  • 相关阅读:
    【linux】(1)文件操作及vi
    连连看游戏页面网站源码
    我在Linux开发板上跑的第一个Qt程序
    xcode15出现大量Duplicate symbols
    Java 类型转换和运算符计算
    DevOps中集成自动化测试的具体案例
    Android Gradle 命令打包AAR
    C语言:栈和队列+leetcode232、leetcode225:队实现栈、栈实现队列、leetcode20括号匹配
    HTML期末大作业:基于HTML+CSS+JavaScript新能源汽车资讯门户网站
    半胱氨酸/半乳糖/苝二酰亚胺功能化Fe3O4四氧化三铁纳米材料|科研试剂
  • 原文地址:https://www.cnblogs.com/zeroll/p/16904162.html