Lambdda表达式( Java 8 )

在Java的语言世界里面,除了基本的数据类型,一切都是对象,例如:String字符串、每个对象实例、数组这些都是对象。在Java中方法是不能完全独立存在的,不能将方法作为参数或者返回值给实例。注意:方法(Method),函数(Function),在Java中是没有函数的,因为Java是一个面向对象编程的语言;函数更多的意义是用来表述面向过程的语言;又或者说"函数是大家的函数,方法是类的方法",不过,不用这么纠结,我们可以认为在Java中方法就是函数,函数就是方法。

为什么出现Lambda表达式

从线程的构建、自定义比较器、Swing等等,这些我们都是匿名内部类的方式去书写。为了简化这些代码的书写,使得代码更加紧凑,更为了使得Java拥有函数式编程的特点。javaScript是典型的函数式编程语言,点击这里以及这里了解,函数式语言提供了一种强大的功能–闭包,闭包的特点是词法的作用域与把函数当作值来传递。虽然闭包与Lambda表达式之间存在显著差别,但是Lambda表达式至少是很好的闭包替代者。

Lambda表达式是什么

在Java中,刚开始说过,除了基本的数据类型,一切都是对象,那么Lambda表达式也是对象,所以必须依赖于一种特殊的对象类型–函数式接口(Function Interface)。Lambda表达式可以理解为刚开始说的匿名内部类函数,它没有声明方法,没有访问修饰符,没有返回值声明和名字。

Lambda表达式的特征
  • 可选型声明:不需要声明参数类型,编译器可以统一识别参数值;
  • 可选的参数圆括号:一个参数且类型可推导时,无需定义圆括号,但是多个参数需要定义圆括号;
  • 可选的大括号:如果函数主体包含了一个语句,不需要大括号;
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要显式指定表达式返回值。
Lambda表达式的用法
  • Lambda表达式语法:(parameters)->expression 或 (parameters)->{statements}
    Lambda表达式语法解析:parameters:参数 expression:表达式(一条语句) statements:陈述(多个语句)

  • 用法
    1. 替代匿名内部类

      实现Runnable接口是匿名内部类的典型例子
      ```java
      // 代码示例
      public void runable() {
          new Thread(new Runnable() {
              @Override
              public void run() {
                  System.out.println("the old runnable now is useing");
              }
          }).start();
    
          new Thread(() -> System.out.println("the new runnable now is useing")).start();
      }
      ```
    

    2. 集合的迭代

      使用Lambda表达式对map集合进行迭代遍历
      ```java
      // 代码示例
      private void listiterator() {
          List<String> languages = Arrays.asList("java", "python", "javaScript");
          languages.forEach(x -> System.out.println(x));
      }
      ```
    

    3. 实现map

      使用Lambda表达式实现map,map的作用是把一个对象换做另一个,这块涉及到Java8的新特性Stream,下一篇博客会讲。
      ```java
      // 代码示例
      private void mapFunction(){
          List<Double> languages = Arrays.asList(2.0, 4.0, 6.0);
          languages.stream().map(x -> x + x * 0.5).forEach((x) -> System.out.println(x));
      }
      ```
    

    4. 实现reduce

      使用Lambda表达式实现reduce,reduce是将所有的值合并为一个,这块涉及到Java8的新特性Stream,下一篇博客会讲。
      ```java
      // 代码示例
      private void sumFunction() {
          List<Double> cost = Arrays.asList(2.0, 4.0, 6.0);
          double doubleCode = cost.stream().reduce((sum, x) -> sum + x).get();
          System.out.println(doubleCode);
      }
      ```
    

    5. 过滤操作

      使用Lambda表达式实现对集合的过滤,filter过滤掉集合中的部分元素,这块涉及到Java8的新特性Stream,下一篇博客会讲。
      ```java
      // 代码示例
      private void filterFunction() {
          List<Double> cost = Arrays.asList(2.0, 4.0, 6.0);
          //方式一
          cost.stream().filter(x -> x > 3).collect(Collectors.toList()).stream().forEach(x -> System.out.println(x));
          //方式二
          List<Double> doubleCode = cost.stream().filter(x -> x > 3).collect(Collectors.toList());
          doubleCode.stream().forEach(x -> System.out.println(x));
      }
      ```
    

    6. 与工具包java.util.function配合
      
      除了在语言层面支持了函数式编程,而且增添了一个新包,包名叫java.util.function。该包包含了很多类,来支持Java的函数式编程,其中一个类是Predicate,使用java.util.function.Predicate 函数式接口以及lambda表达式,可以向API方法添加逻辑,用更少的代码支持更多的动态行为。Predicate接口非常适用于做过滤。该包下的其他类放到姐妹篇里面讲解

函数式接口名作用
Function<T, R>接受一个参数T,返回结果R
Predicate接受一个参数T,返回boolean
Supplier不接受任何参数T,返回结果T
Consumer接受一个参数T,不返回结果
UnaryOperator继承自Function<T,T>,返回相同类型T的结果
BiFunction<T, U, R>接收两个参数T,U,返回结果R
BinaryOperator继承自BiFunction<T,T,T>,返回相同类型T的结果
Runnable实际上不接受任何参数,也不返回结果
Comparable实际上是接受两个相同类型的T,返回int
Callable不接受任何参数,返回结果V
    ```java
    // 代码示例
    public class test {

        public static void main(String[] args) {
            test t = new test();

            List<String> launges = Arrays.asList("java", "shell", "python");
            t.functionTest.apply(launges).stream().forEach(x -> System.out.println(x));

            boolean flg = t.predicateTest.test(launges);
            System.out.println(flg);

        }

        private Function<List<String>, List<String>> functionTest = in -> {
            return in.stream().filter(x -> x.startsWith("j")).collect(Collectors.toList());
        };

        private Predicate<List<String>> predicateTest = in -> {
            return in.stream().filter(x -> x.startsWith("j")).count() > 0;
        };
    }
    ```
Lambda表达式的优劣
  • 优势
    1. 代码简洁
    2. 易并行计算
    3. 方便了函数式编程
    4. 改善了集合的操作(引入了Stream API)
  • 劣势
    1. 代码可读性变差
    2. Debug调试变得困难
    3. 不可以直接在foreach中修改外面的值
    4. 在很多非并行运算中,性能未必有传统的for性能要高

文章借鉴处

  • https://www.cnblogs.com/ysySelf/p/10937725.html
  • https://www.runoob.com/java/java8-lambda-expressions.html
  • http://blog.oneapm.com/apm-tech/226.html
  • https://objcoding.com/2019/03/04/lambda/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值