美文网首页
JAVA8新特性之不得不说的lambda表达式

JAVA8新特性之不得不说的lambda表达式

作者: 先生zeng | 来源:发表于2020-11-29 14:40 被阅读0次

本篇内容

  • 函数式编程
  • 行为参数化
  • 方法引用
  • 匿名函数
  • 函数式接口
  • 一步步演变-lambda表达式

讲真的,在整理这篇文章内容之前,我一直在想要不要整理的这么细节,但俗话说得好,细节决定成败,所以我希望每个对lambda表达式没有概念的同学看过我这篇文章后,都能跟看过一遍java8实战这本书一样,对于lambda表达式出现的前因后果有个比较深入的了解跟理解,同时也能够让已经看过java8实战这本书的内容的人,进一步深入lambda表达式这个概念以及设计的意义。

函数式编程

在JAVA8中引入了比较前沿的就是函数式编程的思想,我们本篇要讲的lambda表达式,一步步演变之前,最开始都是基于我现在说的这个函数式编程的思想。所谓函数式编程,是一种编程范式,我们常见的编程范式有命令式编程(Imperative programming),函数式编程,逻辑式编程,常见的面向对象编程是也是一种命令式编程。

命令式编程是面向计算机硬件的抽象,有变量(对应着存储单元),赋值语句(获取,存储指令),表达式(内存引用和算术运算)和控制语句(跳转指令),一句话,命令式程序就是一个冯诺依曼机的指令序列。

** 而函数式编程是面向数学的抽象,将计算描述为一种表达式求值,一句话,函数式程序就是一个表达式。**
很抽象哈,其实就是你可以把函数当成参数去对待,参数可以承担的角色,函数也可以。在函数式语言中,函数作为"一等公民"(这里是指向),可以在任何地方定义,在函数内或函数外,可以作为函数的参数和返回值,可以对函数进行组合。

在JAVA8中引入的两个最主要的功能,lambda表达式以及stream,都需要基于这种思想来设计。

比如:Java8中从函数式编程中引入的两个核心思想:将方法和Lambda作为一等值,以及在没有可变共享状态时,函数或方法可以有效、安全地并行执行。在我们stream api的设计中,都使用了这两种思想。

后面我会总结出相关内容补上,我们继续来看。下一个

行为参数化

既然前面说了,JAVA8引入了函数式编程的思想的设计,那么如何实现呢?这就需要下面这个功能, 在java8中增加了一种把方法(你自己编写的代码)作为参数传递给另一个方法的能力。所以其实行为参数化就是方法参数化。在我们stream api的设计中也是利用这点:构建在通过传递代码使操作行为实现参数化的思想上的。只有把行为参数化,才可以把函数(或者说行为操作)作为参数传进函数中,进行编程吧。

定义: 就是一个方法可以接受多种不同的行为作为参数,并且在内部使用他们,完成不同行为的能力。可以把一个行为(一段代码,结合匿名类)通过接口封装起来后在调用时候通过lambda方式实现,能够适应不断变化的需求,这种做法类似策略模式。

下面我们还是引用java8实战这本书中的例子: 筛选苹果行为或者方式不同的例子(使用谓词)

我先用一句话总结为什么需要下面的方式写哈,比如你产品经理有个需求,筛选10万个苹果中重量大于50千克的过滤出来。于是你草草写了个遍历、判断重量大于150k、返回结果。这时候客户又提了个需求,筛选10万个苹果中绿色的过滤出来。于是你又草草写了个遍历、判断重量大于150k、返回结果。写完之后,你有点不满意,感觉这代码都差不多啊,还很low,不符合我们减少重复代码原则吧,七七八八的,反正感觉很怪,这时候,产品经理又来了,过滤出红色苹果,小于100g的评估吧。。。于是你小脑筋一动,写了下面一行代码,小小难度。。

public class AppleHeavyWeightPredicate implements ApplePredicate{
       public boolean test(Apple apple){
           return apple.getWeight() > 150;
       }
   }
   public class AppleGreenColorPredicate implements ApplePredicate{
       public boolean test(Apple apple){
           return "green".equals(apple.getColor());
       }
   }
   public class FilteringApples{
       public static void main(String...args){
           List<Apple> inventory = Arrays.asList(new Apple(80,"green"),
                   new Apple(155, "green"),
                   new Apple(120, "red"));
           List<Apple> heavyApples =
                   filterApples(inventory, new AppleHeavyWeightPredicate());
           List<Apple> greenApples =
                   filterApples(inventory, new AppleGreenColorPredicate());
       }
       public static List<Apple> filterApples(List<Apple> inventory,
                                              ApplePredicate p) {
           List<Apple> result = new ArrayList<>();
           for (Apple apple : inventory){
               if (p.test(apple)){
                   result.add(apple);
               }
           }
           return result;
       }
   }

这时候,你发现,虽然代码不冗余了,但是每次新的获取苹果的需求过来(其实我不爱吃苹果,为啥老是让我写苹果),你都要new一个类,实现接口,你发现好像代码实现起来不麻烦,写的很多。你想了下,搞个匿名类吧,于是有了下面一个实现:


于是java8中提供了一个新的概念,叫方法引用的语法。
你灵机一动,赶紧试了一下效果,哎,还不错哦:

使用lambda表达式:

List<Apple> result =
filterApples(inventory, (Apple apple) -> "red".equals(apple.getColor()));

方法引用

方法引用是使用::语法(能够把这个方法作为"值",传递给方法中的参数,而不需要把该方法包含在一个对象中,在再该对象中使用该方法,使用比较简洁)。可以让你重复使用现有的方法实现并传递他们。

lambda表达式=lambda函数=(匿名函数)

一般我们都讲lambda表达式,可能有些童鞋看到这里会很奇怪,前面说的方法引用语法,其实就是将函数作为值的思想的使用,还包括了lambda(或者匿名函数)。

我们可以理解为匿名函数,它没有名称,但有参数列表、函数主体、返回类型,可能还有一个可以抛出异常的列表。

你可以这样写: (int x)-> x + 1 , 这是一个lambda表达式,表示"调用时,给定参数x,就返回x+1值的函数",在java8之前,我们要写一个工具类,然后类中包含一个add方法去调用并返回。但现在只需要一行代码就解决了这个问题了,这就是lambda表达式的第一个优点: 语法更简洁。

在看一个例子:
通常我们在程序开发时,经常需要遍历list,过滤一些条件,每次大概思路都是 : 遍历时判断条件去过滤:代码如下所示

public class Apple {

    public Apple() {
    }

    public Apple(String color, int weight) {
        this.color = color;
        this.weight = weight;
    }

    private String color; // 颜色
    private int weight; // 重量

    //这里省略了color、weight的getter和setter方法。
    
    public static boolean filterRedApple(Apple apple) {
        return "red".equals(apple.getColor());
    }

    public static boolean filterWeightApple(Apple apple) {
        return apple.getWeight() > 150;
    }

    @Override
    public String toString() {
        return "Apple [color=" + color + ", weight=" + weight + "]";
    }
}

上面我们在过滤超重的苹果时,需要写一个方法,遍历时判断苹果的重量。
当我们换了一种条件时,比如过滤红色的苹果计算苹果的总库存,又要写一个方法来去过滤。就会变得有很多重复的代码。

我们可以使用Predicate :

public static boolean isGreenApple(Apple apple) { 
    return "green".equals(apple.getColor());
} 
public static boolean isHeavyApple(Apple apple) { 
    return apple.getWeight() > 150;
} 
// 这部分可以不写,直接导入即可
public interface Predicate<T>{
     boolean test(T t); 
} 
static List<Apple> filterApples(List<Apple> inventory, 
  Predicate<Apple> p) {
      List<Apple> result = new ArrayList<>(); 
      for (Apple apple: inventory){ 
          if (p.test(apple)) { 
              result.add(apple); 
          } 
    } 
  return result; 
} 
要用它的话,你可以写:
filterApples(inventory, Apple::isGreenApple); 
或者
filterApples(inventory, Apple::isHeavyApple);

在java8中,把方法作为值来传递显然很有用,但要是为类似于isHeavyApple和isGreenApple这种可
能只用一两次的短方法写一堆定义有点儿烦人。不过Java 8也解决了这个问题,它引入了一套新
写法法(匿名函数或Lambda),让你可以写
filterApples(inventory, (Apple a) -> "green".equals(a.getColor()) );
或者
filterApples(inventory, (Apple a) -> a.getWeight() > 150 );

这里就引入了一个新的概念,匿名函数与函数式接口,关于函数式接口可以看我这篇文章:
https://www.jianshu.com/p/6b1da190f11c

行为参数化

行为参数化是一个很有用的模式,它能够轻松地适应不断变化的需求。这
种模式可以把一个行为(一段代码)封装起来,并通过传递和使用创建的行为(例如对Apple的不同谓词)将方法的行为参数化。前面提到过,这种做法类似于策略设计模式。

相关文章

  • Java 8、9 语言新特性

    Java语言新特性 Java8 Java 8 新特性 Lambda 表达式 Lambda表达式(也叫做闭包)是Ja...

  • java8 新特性

    java8 新特性 1 Lambda表达式 lambda 是一个匿名函数, lambda 表达式基本语法: jav...

  • Lambda表达式和函数式接口

    初识lambda表达式 lambda表达式是Java8的新特性,可以将lambda表达式看成是精简语法的匿名内部类...

  • Java8 新特性之 Lambda 表达式

    Lambda表达式 lambda表达式是java8给我们带来的几个重量级新特性之一,借用lambda表达式,可以让...

  • Lambda的基础使用

    Lambda是java8出的新特性,之前很少用Lambda表达式写代码,现在慢慢习惯用Lambda表达式,并且记得...

  • java8

    现代化 Java - Java8 指南 JAVA8新特性(吐血整理) 理解 Lambda 表达式

  • Lambda表达式

    内容整理自bilibili 参考链接 一、lambda表达式的简介 lambda表达式是java8添加的新特性; ...

  • Java8 新增了非常多的特性

    新特性Java8 新增了非常多的特性,我们主要讨论以下几个: Lambda 表达式 − Lambda允许把函数作为...

  • Lambda 表达式

    Lambda 表达式 声明:java8新特性系列为个人学习笔记,参考地址点击这里,侵删!! Lambda 表达式,...

  • Java8新特性

    1、语言新特性 1.1、Lambda表达式(也称闭包) Lambda表达式是Java8最大的卖点,它允许交函数作为...

网友评论

      本文标题:JAVA8新特性之不得不说的lambda表达式

      本文链接:https://www.haomeiwen.com/subject/urahiktx.html