JAVA 8 新特性之 Lambda 表达式基础语法

前序:

    1:Lambda 表达式 及支持 jdk 8 或以上 版本2:学习 Lambda 表达式需要了解 “函数式接口”。

    3:用过Idea 编辑器的朋友应该知道,idea 已经支持 lambda 表达式,即使你和我一样还不了解 Lambda表达式 ,你若代码中出现了可以更改成Lambda表达式的代码,idea会自动提示你。
  
   4:即便支持就更要学习一下,要不然你会和我一样闹出笑话(真人真事)。
讲个笑话,最开始接触idea(eclipse 转 idea) 的时候,用Runnable 时,idea 出现黄色警告⚠,那是我第一次接触Lamdba 表达式,当时就很好奇跟同事讲 idea 居然可以这样写。现在想起那个同事的表情,就知道他当时为什么不理我了。

 


 

Lambda 表达式基础语法总结:

  1. 语法格式一:无参,无返回值
    语法:() -> 具体的实现 

    演示对象:我们拿 Runable 来演示
    • 传统代码
      /**
           * 测试
           * @param args
           */
          public static void main(String[] args) {
      
              Runnable runnable=new Runnable() {
                  @Override
                  public void run() {
                      System.out.println("传统方式 无参,无返回值");
                  }
              };
      
              runnable.run();
          }
      
      // 运行结果
      传统方式 无参,无返回值
    • Lambda 表达式:有没有眼前一亮,是不是很简单。
      /**
           * 测试
           * @param args
           */
          public static void main(String[] args) {
      
              Runnable runnable= () -> System.out.println("Lambda 无参,无返回值");
      runnable.run(); }
      //运行结果 Lambda 无参,无返回值
  2. 语法格式二:有一个参数,并且无返回值
    语法:(x)-> 具体的实现
    演示对象:自定义 ”函数式接口“

    与上面不同:这里有了一个 x ,x:表示参数,
    • 自定义一个”函数式接口” 
      /**
       * @author Administrator
       * @version 1.0
       * @describe
       * @date 2019/12/21 20:23
       */
      @FunctionalInterface
      public interface FunctionTest {
          /**
           * 用于对这个数值 进行处理,
           * 交由 子类实现。
           * @param num
           */
          void calculate(int num);
      
      }
    • Lambda 表达式实现:这里的 x 表示形参,是calculate方法 传进来的 10,你也可以不取名为x , 其它的都可以。
      /**
           * 测试
           * @param args
           */
          public static void main(String[] args) {
      
              //需求:打印一个数值中的偶数
              FunctionTest test =(x) ->{
                  for (int i = 0; i < x; i++) {
                      if (i % 2 == 0) {
                          System.out.println(i);
                      }
                  }
              };
              test.calculate(10);
      
      
          }
      
      // 运行结果
      
      0
      2
      4
      6
      8
  3. 语法格式三:若有一个参数,小括号省略不写
    x -> 具体的实现

    演示对象:用 语法格式二 来做演示
    • 代码演示:忽略 x 的小括号,

      /**
           * 测试
           * @param args
           */
          public static void main(String[] args) {
      
              //需求:打印一个数值中 2的倍数
              FunctionTest test = x ->{
                  for (int i = 0; i < x; i++) {
                      if (i % 2 == 0) {
                          System.out.println(i);
                      }
                  }
              };
              test.calculate(10);
          }
      
      #运行结果 
      0
      2
      4
      6
      8
  4. 语法格式四:若存在多个参数、多条语句时,那么必须 带 {}。
    (x,y) ->{具体的实现}
    演示对象:自定义” 函数接口 “,
    强调:若存在多个参数时,必须带上"小括号",取什么名无所谓,不重复即可。
    • 自定义”函数接口“
      /**
       * @author Administrator
       * @version 1.0
       * @describe
       * @date 2019/12/21 20:23
       */
      @FunctionalInterface
      public interface FunctionTest {
          /**
           * 用于对两个数值 进行处理,
           * 交由 子类实现。
           * @param num1
           * @param num2
           */
          void calculate(double num1,double num2);
      
      }
    • Lambda 表达式实现方式一:计算两个数的和
      /**
           * 测试
           * @param args
           */
          public static void main(String[] args) {
      
              //需求:打印一个数值中 2的倍数
              FunctionTest test = (x,y) -> System.out.println(String.format("%s + %s = %s",x,y,x+y));
              test.calculate(5,3);
          }
        // 运行结果
        5.0 + 3.0 = 8.0

       

    • Lambda 表达式实现方式二:计算两个数的 积
      /**
           * 测试
           * @param args
           */
          public static void main(String[] args) {
      
              //需求:打印一个数值中 2的倍数
              FunctionTest test = (x,y) -> System.out.println(String.format("%s x %s = %s",x,y,x*y));
              test.calculate(4,6);
          }
        // 运行结果
        4.0 x 6.0 = 24.0

       

    • Lambda表达式实现方式三:上面都是 单条语句的,下面实现多条语句,分别输出两个参数的值就行了。
      /**
           * 测试
           * @param args
           */
          public static void main(String[] args) {
      
              //需求:打印一个数值中 2的倍数
              FunctionTest test = (x,y) ->{
                  System.out.println(String.format("x = %s",x));
                  System.out.println(String.format("y = %s",y));
              };
              test.calculate(4,6);
          }
      
      //运行结果
      x = 4.0
      y = 6.0

       

    • 传统方式实现:
      第一种方式:创建一个子类由子类来实现。
        这里就不介绍 第一种方式了,太麻烦还得创建一个新的类。
      第二种方式:采用匿名内部类的方式进行实现。
    • 采用 匿名内部类的方式进行实现两个数(4 和 5)的和
      public static void test(double x,double y,FunctionTest test){
              test.calculate(x,y);
          }
      
            /**
           * 测试
           * @param args
           */
          public static void main(String[] args) {
      
             //匿名内部类的方式进行实现
              test(4, 5, new FunctionTest() {
                  @Override
                  public void calculate(double num1, double num2) {
                      System.out.println(num1* num2);
                  }
              });
      
          }
      
      
      // 运行结果:
          20.0

  5. 语法格式五:若存在多个参数、单条语句时,return 或 {} 可以省略不写。

    • 代码上面已经演示过了,但是上面的案例都是无返回值的,那么看看有返回值的情况下是怎么样的
    • 更改一下 接口方法。
      /**
       * @author Administrator
       * @version 1.0
       * @describe
       * @date 2019/12/21 20:23
       */
      @FunctionalInterface
      public interface FunctionTest {
          /**
           * 用于对这个数值 进行处理,
           * 交由 子类实现。
           * @param num1
           * @param num2
           */
          double calculate(double num1,double num2);
      
      
      }
    • 代码演示 有返回值的 Lambda 表达式
            /**
           * 测试
           * @param args
           */
          public static void main(String[] args) {
              FunctionTest test=(x,y) ->{
                  double result = x * y;
                  return result;
              };
      
              System.out.println(test.calculate(10,2));
      
          }
      
      
      # 运行结果
      20.0

  6. 语法格式六:Lambda 表示的参数列表的参数类型可以省略不写,因为JVM编辑器通过上下文推断出,数据类型,即“类型推断”。

 


 

JAVA 内置四大核心 函数接口

上面的案例中,每写一个案例,都需要自己创建一个 “函数接口”,在java 中已经为我们内置好了一些“函数接口”,对于一些普通的操作,我们就无需再自己去创建接口。但是面对比较复杂的业务时,还是需要我们自己来创建的。

只要这四大函数接口能充分掌握了,那么其他的也就水到渠成了。
  • 四大核心 函数接口 分类
    名称 定义 方法  解释
    Consumer<T> 消费型接口 void accept(T t); 消费型接口,主要用于做一些无返回值数据处理,最简单的案例就是 在里面输出一句话 System.out.println("hello word!")。 
    Supplier<T> 供给型接口 T get() 供给型接口,主要是用于提供一些资源响应。如Random.nextInt()方法,它就是产生一些随机数并返回。默默的奉献着,不收取人任何回报
    Function<T,R> 函数型接口 R apply(T t) 函数型接口,有两个参数(T、R),对 T 进行处理,返回 R。 
    Predicate<T> 断言型接口 boolean test(T t) 主要用于做一些判断型操作。 

 

 

 

 

 

 

 

 

 

  •  Consumer 案例演示
      /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            List<Integer> numbers=new ArrayList<>();
            numbers.add(52);
            numbers.add(18);
            numbers.add(45);
            numbers.add(12);
            numbers.add(63);
    
    
            //案例: 将上列数据 按照 升序进行排列
            Consumer<List<Integer>> consumer=(t)->{
                int size = numbers.size();
                for (int i = 0; i < size-1; i++) {
                    for (int j = 0; j < size-1-i; j++) {
                        //比较两个整数的大小
                        if (numbers.get(j)>numbers.get(j+1)) {
                            Integer temp = numbers.get(j);
    //                  使用list集合的set方法,找到位置并将数字赋值到该位置
                            numbers.set(j, numbers.get(j+1));
                            numbers.set(j+1,temp);
                        }
                    }
                }
            };
            consumer.accept(numbers);
    
            for (int i = 0; i < numbers.size(); i++) {
                System.out.println(numbers.get(i));
            }
    
        }
  • Consumer 案例结果
    12
    18
    45
    52
    63
  • 也可以这样实现。
       /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            List<Integer> numbers=new ArrayList<>();
            numbers.add(52);
            numbers.add(18);
            numbers.add(45);
            numbers.add(12);
            numbers.add(63);
    
    
            sort(numbers,(t)->{
                int size =numbers.size();
                for (int i = 0; i < size-1; i++) {
                    for (int j = 0; j < size-1-i; j++) {
                        //比较两个整数的大小
                        if (numbers.get(j)>numbers.get(j+1)) {
                            Integer temp = numbers.get(j);
    //                  使用list集合的set方法,找到位置并将数字赋值到该位置
                            numbers.set(j, numbers.get(j+1));
                            numbers.set(j+1,temp);
                        }
                    }
                }
    
            });
            //打印 排序后的结果
            System.out.println(numbers);
    
    
        }
      // 自定义方法,这样的方式会更加灵活,
        public static void sort(List<Integer> list, Consumer consumer){
            consumer.accept(list);
        }

      // 运行结果
      [12, 18, 45, 52, 63]
     
  • Supplier 案例演示:
    需求:根据用户输入条件 匹配 用户信息并返回。
    如:用户输入 一个 数据 16,那么匹配用户集合中包含 16 的数据信息。并做返回。
    
    定义一个 三条用户数据信息,存放到 集合中。
    然后 采用 Supplier 供给型函数接口 实现数据匹配。

     

      /**
         * 测试 定义一个map list 模拟 用户信息,
         * @param args
         */
        public static void main(String[] args) {
           List<Map<String,String>> nameList=new ArrayList<>();
           Map<String,String> user1=new HashMap<>(5);
            user1.put("姓名","张三");
            user1.put("年龄","18");
            user1.put("性别","男");
            nameList.add(user1);
    
            Map<String,String> user2=new HashMap<>(5);
            user2.put("姓名","春丽");
            user2.put("年龄","16");
            user2.put("性别","女");
            nameList.add(user2);
    
            Map<String,String> user3=new HashMap<>(5);
            user3.put("姓名","小明");
            user3.put("年龄","16");
            user3.put("性别","男");
            nameList.add(user3);
    
            //根据 数据为16 的用户信息
            List< Map<String,String>> maps= queryUserName( nameList,()->"16");
    
            System.out.println(maps);
    
        }
    
        /**
         * 根据用户输入条件,匹配用户信息并返回
         * @param mapList
         * @param supplier
         * @return
         */
        public static  List< Map<String,String>> queryUserName( List<Map<String,String>> mapList,Supplier<String> supplier){
            List< Map<String,String>> mapList1=new ArrayList<>();
    
            for (int i = 0; i < mapList.size(); i++) {
                Map<String,String> map=mapList.get(i);
                for (String key: map.keySet()){
                    if (map.get(key).equals(supplier.get())) {
                        mapList1.add(map);
                        continue;
                    }
                }
    
            }
    
            return mapList1;
        }
  • Supplier 案例 运行结果:
    //包含 16 的数据 有 两条
    
    [{姓名=春丽, 年龄=16, 性别=女}, {姓名=小明, 年龄=16, 性别=男}]

     

  • 若上面的案例太复杂,可以简单的使用 Supplier :实际上在工作中,肯定不会这么写(如下),业务肯定这个复杂,一个复杂 一个简单的对比,只是想说明 supplier 的作用。更想说明 Lambda 表达式的好处
       /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            //生成一个 随机数
            Supplier supplier =() -> new Random().nextInt();
            System.out.println(supplier.get());
    
        }
    
        // 运行结果
        1144876318 
  • Function 案例展示:
    需求:对字符串进行处理。

     

          /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            //小写处理
            String toLowerCase = strHandler("Hello, Word!",(t)-> t.toLowerCase() );
            System.out.println(toLowerCase);
            //大写处理
            String toUpperCase = strHandler("Hello, Word!",(t)-> t.toUpperCase() );
            System.out.println(toUpperCase);
    
        }
    
        /**
         * 对字符串进行处理
         * @param str
         * @param function
         * @return
         */
        public static String strHandler(String str, Function<String,String> function){
            return function.apply(str);
        }

     

  • Function 案例 运行结果:
    hello, word!
    HELLO, WORD!

     

  • Predicate 案例展示:
    检测 用户是否输入的是数字
  •  实现代码
      /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
    
    
            // 测试数据
            String str= "12";
    
           boolean bool= numberVerification(str,(s)->{
                Pattern pattern = Pattern.compile("^-?\\d+(\\.\\d+)?$");
    
                Matcher isNum = pattern.matcher(s);
                if (!isNum.matches()) {
                    return false;
                }
                return true;
            });
    
            System.out.println(bool);
            
        }
    
        /**
         * 检测用户输入是否为数字
         * @param str
         * @param predicate
         * @return
         */
        public static boolean numberVerification(String str, Predicate<String> predicate){
            return predicate.test(str);
        }
  • Predicate 案例运行结果:
    true

     

 

 最后总结:

说实话,我案例表述的不是很明白,若你想要好好的学习一下 Lambda 表达式 建议 去 B站 找视频系统学习。以上案例 都是我看视频时,练手用的代码。至于质量而已,我能明白就行了,我又不是行业大佬,也没想过能写出高质量博客,只是记录一下我的学习过程罢了。
你看了,有所感悟,我也很高兴,若是没有帮助,关掉就行了。

 

 

 

后续更新中....

posted @ 2019-12-22 13:35  不朽_张  阅读(188)  评论(0)    收藏  举报