首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >java8新特性之Lambda表达式

java8新特性之Lambda表达式

作者头像
用户8902830
发布于 2021-08-12 03:00:07
发布于 2021-08-12 03:00:07
33200
代码可运行
举报
文章被收录于专栏:CodeNoneCodeNone
运行总次数:0
代码可运行

java8在2014年就推出了,整天喊着8版本稳定,企业都用jdk8,结果8的特性现在才系统的学,罪过罪过啊!此系列博客可能3-4篇,带你全面地了解java8新特性。

其实我平常学习的时候看某些入门博客,总担心写的不全,所以希望自己以后写的技术博客能够把必须的尽可能全的总结出来,做到看一篇就能够入门的水平。

lambda快速体验

入门最快就是看demo啦,现在有个需求,让你在众多苹果中挑选出红色的苹果

  • 苹果类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Apple {
    String color;
    int weight;
    //省略构造函数,get方法
}
写法1:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static List<Apple> filterGreenAppleWithNormal(List<Apple> apples) {
    List<Apple> res = new ArrayList<>();
    for (Apple apple : apples) {
        if ("red".equals(apple.getColor())) {
            res.add(apple);
        }
    }
    return res;
}

//调用
List<Apple> normal = filterGreenAppleWithNormal(apples);

如果再有一个需求说挑选出绿色的苹果呢,按照这种写法就需要创建一个新的类,然后仅仅把"red" 修改成"green" 其它都不变,这明显是不显示的。所以可以把颜色当成参数传进去

写法2:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static List<Apple> filterGreenAppleWithArg(List<Apple> apples, String color) {
    List<Apple> res = new ArrayList<>();
    for (Apple apple : apples) {
        if (color.equals(apple.getColor())) {
            res.add(apple);
        }
    }
    return res;
}

//调用
List<Apple> arg = filterGreenAppleWithArg(apples, "red");

此时再有一个需求,需要筛选出一定重量或者某个颜色的苹果,需要怎么办呢,按照上述想法是把能想到的属性都堆到方法的参数中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static List<Apple> filterWeightOrColorWithArg(List<Apple> apples, String color, int weight, boolean flag) {
    List<Apple> res = new ArrayList<>();

    for (Apple apple : apples) {
        if (flag && color.equals(apple.getColor()) || !flag && apple.getWeight() > weight) {
            res.add(apple);
        }
    }
    return res;
}

//调用
List<Apple> weightOrColor = filterWeightOrColorWithArg(apples, "", 500, false);

可以这样写吗,当然可以解决问题,但是如果有5个属性呢,6个属性呢,还有,参数中的flag是什么意思呢。

仔细一想,筛选颜色,筛选重量,这些的本质是在筛选,是一个行为(后面更专业称谓语),可以把行为抽象成一个接口

  • 行为接口
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface AppleFilter {
    boolean filter(Apple apple);
}
写法3:

首先需要实现这个接口来具体化行为

  • 筛选红色苹果实现类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class RedFilter implements AppleFilter {
    @Override
    public boolean filter(Apple apple) {
        return "red".equals(apple.getColor());
    }
}

回到使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static List<Apple> filterApples(List<Apple> apples, AppleFilter filter) {
    List<Apple> res = new ArrayList<>();

    for (Apple apple : apples) {
        if (filter.filter(apple)) {
            res.add(apple);
        }
    }

    return res;
}

//调用
List<Apple> behavior = filterApples(apples, new GreenFilter());

这样看就舒服多了,当有新需求的时候,只需要再添加一个类,比如需求是筛选出重量超200g的苹果,只需要新建一个筛选类实现上述接口即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class WeightGt200Filter implements AppleFilter {
    @Override
    public boolean filter(Apple apple) {
        return apple.getWeight() > 200;
    }
}

还能怎样精简代码呢?熟悉Java的小伙伴到这里应该就想到了匿名内部类

写法4:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
List<Apple> innerClass = filterApples(apples, new AppleFilter() {
    @Override
    public boolean filter(Apple apple) {
        return "green".equals(apple.getColor());
    }
});

一般到这一步,比较不错的IDE就会开始提醒建议了

image-20210413193608641

这就到了我们今天的重点,lambda表达式

写法5:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
List<Apple> lambda = filterApples(apples, apple -> apple.getWeight() > 500);

没错,就是这么精简,不过filterApples 这个方法是不能省略的,但是扩展性相较1,2,简洁性相较3,4都好了很多

什么是lambda

可以把Lamdba表达式理解为简洁地表示可传递的匿名函数的一种形式:它没有名称,但它有参数列表、函数主题、返回类型,可能还有一个可以抛出的异常列表

书写格式: (参数) -> {主体}

正如上面写法5一样(apple) -> {apple.getWeight() > 500;}

  • lambda表达式对参数能够自动推断类型,当然也可以显示书写类型
  • 没有return语句,应为已经有隐含了return
  • lambda中可以有多行语句

使用案例:

  • () -> {}
  • () -> "java"
  • () -> {return "java";}
  • (int a, int b) -> a * b
  • () -> {System.out.println("hello"); System.out.println("java");}

如何才能使用lambda

使用函数式接口的时候才能使用lambda表达式

所谓函数式接口就是仅仅定义了一个抽象方法,比如一开始把行为抽象成一个AppleFilter 接口,该接口只有一个filter() 方法。注意是只有一个抽象方法,并不是只有一个方法,通俗来说是继承该接口的类只需要实现一个方法。

最常见的两个接口是ComparatorRunnable

image-20210413200933737

后来为了更方便地区分函数式接口,Java新的API中多了一个@FuntionalInterface ,该注解仅仅是表明该类是函数式接口(并不是必须的),如果有该注解的同时声明了两个抽象方法,那么将会报错

image-20210413201531957

java.util.function下4个常用的函数式接口

java.util.function 下主要有4个常用的函数式接口,FunctionPredicateConsumerPredicate ,随便截取其中的一个源码片段来看,其实也没啥好看的

image-20210413202124036

对这些函数式接口也是得看接口是如何声明的,这里就拿Predicate 举例,该接口主要是对传进来的对象进行一个处理,然后返回boolean 值。是不是有点熟悉,没错,就是和筛选苹果一样

  • predicateDemo
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static List<Apple> predicateDemo(List<Apple> apples, Predicate<Apple> predicate) {
    List<Apple> res = new ArrayList<>();
    for (Apple apple : apples) {
        if (predicate.test(apple)) {
            res.add(apple);
        }
    }
    return res;
}

//调用
List<Apple> predicate = predicateDemo(apples, apple -> "green".equals(apple.getColor()));

其他的也是同理,上才艺

  • functionDemo
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static List<Integer> functionDemo(List<Integer> nums, Function<Integer, Integer> function) {
    List<Integer> res = new ArrayList<>();
    for (int num : nums) {
        res.add(function.apply(num));
    }
    return res;
}

//调用
List<Integer> function = functionDemo(Arrays.asList(1, 8, 7, 3, 9, 2), (num) -> num * 2);
  • consumerDemo
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void consumerDemo(List<Integer> list, Consumer<Integer> consumer) {
    for (int num : list) {
        consumer.accept(num);
    }
}

//调用
consumerDemo(Arrays.asList(1, 5, 6), (num) -> System.out.println(num));
consumerDemo(Arrays.asList(1, 5, 6), System.out::println);
  • supplierDemo
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void supplierDemo(List<Integer> nums, Supplier<String> supplier) {
    StringBuilder sb = new StringBuilder();
    for (int num : nums) {
        sb.append(num).append(supplier.get());
    }
    System.out.println(sb);
}

//调用
supplierDemo(Arrays.asList(1, 5, 6), ()->"java");

方法引用

上面的lambda写法是最精简的吗,不,不是的,还有最最最精简的写法,那就是利用方法引用

方法引用主要有3类:

  • 指向静态方法的方法引用
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Comparator<Integer> normalComparator = (a, b) -> a.compareTo(b);
Comparator<Integer> referenceComparator = Integer::compareTo;
  • 指向任一类型实例方法的方法引用
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Function<String, Integer> normalFunction = (str) -> str.length();
Function<String, Integer> referenceFunction = String::length;

BiPredicate<List<String>, String> normalPredicate = (strings, str) -> strings.contains(str);
BiPredicate<List<String>, String> referencePredicate = List::contains;
  • 指向现有对象的实例方法引用
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Apple apple = new Apple();
Supplier<Integer> normal = () -> apple.getWeight();
Supplier<Integer> reference = apple::getWeight;
  • 当然也可以用于构造函数
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Supplier<Apple> normalSupplier = () -> new Apple();
Supplier<Apple> referenceSupplier = Apple::new;

总结

以上就是java8中的lambda表达式,还有一些知识点是没有讲的,但是觉得不是特别必须,比如类型推断是怎么推断的,还有Lambda复合,抛出异常,拆箱装箱同样没有讲。然后一些东西也不是全盘托出,需要各位小伙伴去idea中进入到源码观看。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CodeNone 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java8学习(3)- Lambda 表达式
猪脚:以下内容参考《Java 8 in Action》 本次学习内容: Lambda 基本模式 环绕执行模式 函数式接口,类型推断 方法引用 Lambda 复合 代码: https://github.com/Ryan-Miao/someTest/blob/master/src/main/java/com/test/java8/c3/AppleSort.java 上一篇: Java8学习(2)- 通过行为参数化传递代码--lambda代替策略模式 ---- 1. 结构 初始化一个比较器: Comparato
Ryan-Miao
2018/03/13
1.1K0
Java8学习(3)- Lambda 表达式
Java8新特性学习之一:lambda表达式入门
最近在系统性学习一些java8的新特性,说一下为什么打算系统的学习它呢。有下面几个原因:1、源码中经常有看到lambda表达式、Stream、Optional、LocalDate、LocalTime;2、从某书上看到java推荐函数式编程、并且新特性的内容性能提升了很多;3、装逼。如果你也对它感兴趣,那么从现在开始,咱们一起来学习吧,今天先将一下lambda表达式的入门、以及使用lambda表达式会给我们带来什么好处,我会从实际的例子出发,跟大家一起学习,绝对通俗易懂。
全栈程序员站长
2022/07/04
2150
Lambda 深入浅出
非常简单,那么问题来了,如果这个时候需求变动,要求选择的是红色的并且重量大于10的,那么怎么办。小 case,不就一行代码的事
breezedancer
2018/09/12
4060
从强耦合到行为化参数最终到 Lambda 表达式
 首先给出本次讨论的背景。农民希望你能够进行苹果库存的筛选,不过他作为甲方,需求经常会改变。
Fisherman渔夫
2020/03/18
5980
Java8__lambda表达式
行为参数化(behavior parameterization)是用来处理频繁更改的需求的一种软件开发模式,可以将一段代码块当做参数传给另一个方法,稍后执行。这样,这个方法的行为就基于那块代码被参数化了。
shirayner
2022/03/11
4400
Java8__lambda表达式
《Java8 实战》- 读书笔记第一章(01)
自 1996 年 JDK(1.0)发布以来,Java 已经受到了学生、项目经理和 程序员等一大批活跃的用户的欢迎。这一语言极富活力,不断被用在大大小小的项目里。从 Java1.1(1997)年一直到 Java7(2011)年,Java 通过增加新功能,不断得到良好的升级。Java8 则是在 2014 年 3 月发布的。那么问题来了:为什么你应该关心 Java8?
小破孩的梦想空间
2022/05/10
3590
Java函数式编程之Java8四大函数接口
在Java8中,内置了四个核心函数接口,它们存在是Lamda表达式出现的前提,Lamda表达式想重写函数式接口中的唯一方法。 函数式接口与Lambda表达式之间的关系:lambda表达式相当于是一个行为,传入函数式接口中,进来实现各种操作,即行为参数化 它们的接口内只有一个抽象方法,每一个函数式接口都有@FunctionalInterface注解。
全栈程序员站长
2022/07/31
5850
Java函数式编程之Java8四大函数接口
java8新特性(一):Lambda表达式
Lambda 是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
周三不加班
2019/09/03
4230
java8新特性(一):Lambda表达式
Java8新特性--Lambda表达式
Lambda 是一个匿名函数,我们可以把Lambda 表达式理解为是一段可以传递的代码(将代码 像数据一样进行传递)。可以写出更简洁、更 灵活的代码。作为一种更紧凑的代码风格,使 Java的语言表达能力得到了提升。
别团等shy哥发育
2023/02/25
4090
Java8新特性——Lambda表达式(一)
1. 预备知识 在了解Lambda表达式之前首先需要了解以下预备知识。 1.1 如何成为一名高级码农? 如果老板让你写一个用于毁灭地球的函数,而你写了一个毁灭行星的函数,若要毁灭地球只需将毁灭地球的过程传递给“毁灭行星”。能做到这一点,你就是一名高级码农。 以上这个问题体现了程序可扩展性的思想。总结一下,要成为一名高级码农,在编码的时候要以发展的眼光看待问题。一个具体问题到来的时候,你需要基于当前问题抽象出解决这一类问题的办法,那么当相似的问题到来时,你只需花少量的时间就能完成任务,而且避免了代码复制,降
大闲人柴毛毛
2018/03/09
8520
Java8新特性学习之二:lambda表达式深入学习
前面我们已经学习过lambda的入门,也感性的了解了lambda可以帮助我们解决什么问题,今天跟大家一起深入的学习如何使用、以及在哪里使用lambda表达式。如果你希望在看源码中遇到了lambda表达式不会抓狂;你希望你的代码更加优雅、简洁、或者装逼专用,咱们一起来学习。
全栈程序员站长
2022/07/04
2830
Java8新特性学习之二:lambda表达式深入学习
Java8新特性----Lambda表达式详细探讨
​ Lambda是一个匿名函数,可以理解为一段可以传递的代码(将代码像数据一样传递);可以写出更简洁、更灵活的代码;作为一种更紧凑的代码风格,是Java语言表达能力得到提升
大忽悠爱学习
2021/11/15
3030
Java 8——行为参数化
前言 《Java8实战》不得不说是一本好书,捧起来看起来就兴奋得不想放下,其中介绍的函数式编程实在是太令人兴奋了,不仅仅大大提高了代码的可读性,而且提高了代码的重用性,并且语法简单。 Java 8中新增的功能是自Java 1.0发布以来18年以来,发生变化最大的一次。我本身没有太大的体会,但新增的这些功能,每一个都让我兴奋,这里就书中的内容简单的介绍一下Java 8的这些新特性,我相信很快,你也会有跟我一样的感受。 (1)用行为参数化把代码传递给方法 Java 8中增加了通过API来传递代码的能力,但这实在
我没有三颗心脏
2018/04/26
1K0
Java 8——行为参数化
Java8 in action(1) 通过行为参数化传递代码--lambda代替策略模式
猪脚:以下内容参考《Java 8 in Action》 发布:https://ryan-miao.github.io/2017/07/15/java8-in-action-2/ 源码:github 需求 果农需要筛选苹果,可能想要绿色的,也可能想要红色的,可能想要大苹果(>150g),也可能需要红的大苹果。基于此等条件,编写筛选的代码。 1. 策略模式解决方案 1.1 最直观的做法 首先,已知信息是一筐苹果(List<Apple> inventory),但筛选条件多种多样。我们可以根据不同的条件写不同的方
Ryan-Miao
2018/03/13
9520
Java杂谈之行为参数化
在软件工程中,一个众所周知的问题就是,不管做什么,用户的需求肯定会变。比方说,有个应用程序是帮助农民了解自己的库存的。这位农民可能想有一个查找库存中所有绿色苹果的功能。但到了第二天,他可能会告诉你:“其实我还想找出所有重量超过150克的苹果。”又过了两天,农民又跑回来补充道:“要是我可以找出所有既是绿色,重量也超过150克的苹果,那就太棒了。”要如何应对这样不断变化的需求?理想的状态下,应该把工作量降到最少。此外,类似的新功能实现起来还应该很简单,而且易于长期维护。
你呀不牛
2021/05/28
4430
系统学习Lambda表达式
在《挑苹果中的行为参数化思想》已经介绍了用Lambda表达式将行为抽象化,对Lambda表达式有一定认识。而本文将对Lambda表达式进行系统性的介绍。
草捏子
2020/08/10
6480
系统学习Lambda表达式
java8实战读书笔记:Lambda表达式语法与函数式编程接口
测试:如下语句是否是正确的lambda表达式。 (1) () -> {} (2) () -> "Raoul" (3) () -> {return "Mario";} (4) (Integer i) -> return "Alan" + i; (5) (String s) -> {"IronMan";}
丁威
2019/06/11
5670
java8实战读书笔记:Lambda表达式语法与函数式编程接口
Java8之熟透Lambda表达式
​ Lambda 表达式可以理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。
用户1195962
2019/09/29
5990
Java8之熟透Lambda表达式
JDK1.8新特性之Lambda表达式
Java8中引入了一个新的操作符“ -> ”,该操作符被称为箭头操作符或Lambda操作符,箭头操作符将Lambda表达式拆分成两部分:
程序员波特
2024/01/19
1900
最火的java8新特性:Lambda 表达式
1. Lambda 表达式 2. 函数式接口 3. 方法引用与构造器引用 4. Stream API 5. 其他新特性
公众号 IT老哥
2020/09/16
4570
相关推荐
Java8学习(3)- Lambda 表达式
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档