java8之lambda表达式

2023-11-19

java8

近期,在一个不完全的统计中,java8的普及率已经到达了近80%。
图【1】
相比之前的java版本,下面两个是java8出现带来最大的影响:其一是极大地简化了代码的复杂度尤其是在处理集合以及接口这两个方面。除此之外,java8引入了流概念,来避免或减少使用多线程的同时利用机器多核来加快代码的执行效率。

本篇文章主要介绍java8的第一个特性————lambda表达式。

介绍:

在java7及更早的版本,当我们会遇到这样的场景:当要实现一个接口尤其是匿名类接口,往往需要写很多模板式的代码;当我们要遍历一个集合做出筛选的时候会使用很多for循环以及if判断语句,这些代码往往导致代码显得十分臃肿。
而java8出现的Lambda表达式可以很好地解决上面的问题。它可以让你很简洁地表示一个行为或传递代码。你可以把Lambda表达式看作匿名的功能,它基上就是没有声明名称的方法,但和匿名类一样,它也可以作为参数传递给一个方法。
例子:

        //普通表达式1
        Runnable runnable2 = new Runnable() {
            @Override
            public void run() {
                System.out.println("a");
            }
        };
        Thread thread1 = new Thread(runnable2);
        thread1.start();

        //lambda表达式1
        Runnable runnable = () -> System.out.println("a");
        Thread thread=new Thread(runnable);
        thread.start();

        //普通表达式2
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("a");
            }
        });

        //lambda表达式2
        Thread thread3 = new Thread(()-> System.out.println("a"));
        thread.start();

上面的例子通过runnable例子分别使用了普通的匿名类和lambda的方式实现线程接口。可以发现使用Lambda表达式可以使我们的代码变得更加简洁。

在哪里使用:

当然,并不是所有的接口都能使用lambda表达式。只有是函数型接口的时候才能使用。
函数型接口指接口只定义了一个抽象方法的接口。例如ranable方法,只定义了一个run方法:

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

其中,为了更好的支持函数式接口,在java8中增加了@FunctionalInterface注解,只要使用了@FunctionalInterface注解的接口只能定义一个抽象方法,否则就会报错。

如何使用:

案例

我们可以通过一个例子一步步掌握和熟悉lambda表达式。以下例子来自java 8实战
首先有一个苹果类:

public class Apple {
    private String color;
    private int weight;

    public Apple() {
    }

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

    public void setColor(String color) {
        this.color = color;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "color='" + color + '\'' +
                ", weight=" + weight +
                '}';
    }
}
第一次尝试

现在我们要从苹果堆中找出绿色的苹果。

public static List<Apple> filterGreenApples(List<Apple> inventory) {
        List<Apple> result = new ArrayList<Apple>();
        for (Apple apple : inventory) {
            if ("green".equals(apple.getColor())) {
                result.add(apple);
            }
        }
        return result;
    }

我们传入一堆苹果,逐个判断他的颜色是否是绿色,但是这种方式不利于代码的扩展,当我们需要筛选红色、白色、黄色苹果都需要修改代码。

第二次尝试:颜色参数

我们可以给方法传一个颜色的参数,来满足筛选不同颜色的苹果:

public static List<Apple> filterApplesByColor(List<Apple> lists, String color) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : lists) {
            if (apple.getColor().equals(color)) {
                result.add(apple);
            }
        }
        return result;
    }

但是,有一天我们需要筛选不同重量的苹果时,上述的方法不能满足我们需求了,于是我们又新建了另一个方法:

 public static List<Apple> filterApplesByWeight(List<Apple> inventory, int weight) {
        List<Apple> result = new ArrayList<Apple>();
        for (Apple apple : inventory) {
            if (apple.getWeight() > weight) {
                result.add(apple);
            }
        }
        return result;
    }

虽然满足我们的需求,但是筛选苹果和筛选重量的方法大部分的代码是一样的,只有判别的方式不同,我们可以提取大部分的代码。

第三次尝试:对你能想到的每个属性做筛选

第三种尝试,是增加了字段来判断是来判断苹果还是重量。

public static List<Apple> filterApples(List<Apple> inventory, String color, int weight, boolean flag) {
        List<Apple> result = new ArrayList<Apple>();
        for (Apple apple : inventory) {
            if ((flag && apple.getColor().equals(color)) || (!flag && apple.getWeight() > weight)) {
                result.add(apple);
            }
        }
        return result;
    }

但是仔细思考之后,这只方式反而是最不好的。首先,他还是只能筛选一个条件,其次,他还是不能做扩展,例如筛选大小,形状等等。

第四次尝试:行为参数化

我们可以创建一个接口,用它来传递我们的筛选规则

public interface ApplePredicate{
    boolean test (Apple apple);
}
public static <T> List<T> filterApple(List<T> lists, ApplePredicate<T> predicate) {
        List<T> result = new ArrayList<>();
        for (T e : lists) {
            if (predicate.test(e)) {
                result.add(e);
            }
        }
        return result;
    }
public class AppleRedAndHeavyPredicate implements ApplePredicate{ public boolean test(Apple apple){
            return "red".equals(apple.getColor())
                && apple.getWeight() > 150;
} }
List<Apple> redAndHeavyApples =filterApples(inventory, new AppleRedAndHeavyPredicate());

这样可以通过用接口的方式来满足我们不同对的苹果进行筛选。

第五次尝试:匿名内部类

但是在第四次尝试中,我们每次新的筛选而创建的类只是用一次,可以使用匿名类类的方式来实现接口。

List<Apple> redApples = filterApples(list, new ApplePredicate() {
            @Override
            public Boolean test(Apple apple) {
                return "red".equals(apple.getColor());
            }
        });
第六次尝试:lambda表达式

上面的代码在java 8里可以用Lambda表达式重写为下面的样子:

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

java原生接口

在java8中增加了原生的函数式接口提供我们来使用lambda,例如所有java.util.function 包下的接口都是函数式接口,都可以使用lambda表达式。

@FunctionalInterface
public interface Supplier<T> {
    T get();
}
@FunctionalInterface
    public interface Function<T, R>{
        R apply(T t);
    }
@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}

速度测试

实质分析

存在的问题

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java8之lambda表达式 的相关文章

随机推荐

  • ubuntu 串口助手通信收发数据不一致

    文章目录 问题背景 一 解决方案 1 直接更换硬件 靠这个解决的 2 其他参考 总结 问题背景 主机1 win10笔记本电脑 主机2 ubuntu16 04的宸曜工控机 主机3 ubuntu14 04的一个小盒子 串口助手 cutecom
  • pmd java规则_静态代码扫描 (一)——PMD 自定义规则入门

    阅读该文章前 最好已经对 PMD 有了初步的认识和了解 可参考静态分析工具 PMD 使用说明 准备工作 首先在PMD 官网下载最新版本的文件 目前最新版本是 5 4 1 下载 pmd bin 5 4 1 zip 和 pmd src 5 4
  • QT串口助手的实现

    serial c include serial h include ui serial h serial serial QWidget parent QWidget parent ui new Ui serial ui gt setupUi
  • 【数据库】MySQL三大日志:binlog、redo log和undo log

    MySQL三大日志 binlog redo log和undo log 日志是mysql数据库的重要组成部分 记录着数据库运行期间各种状态信息 mysql日志主要包括错误日志 查询日志 慢查询日志 事务日志 二进制日志几大类 作为开发 我们重
  • 土壤含水量仪的监测方法

    土壤含水量监测仪对土壤内部水分含量情况进行监测 可实现对灾害隐患点土壤含水量的长期实时监测 仪器主机采用低功耗设计 工作功耗可达毫瓦级 根据滑坡隐患点的特点 仪器主机采用多通道设计 可根据实际情况接驳1 4路土壤含水量传感器对监测点不同深度
  • Python安全攻防之第二章Python语言基础

    2 3 Python模块的安装与使用 python模块的安装 pip3 install 模块名称 py 3 m pip install 模块名称 python模块的导入与使用 1 Import模块名称 采用 Import模块名称 方式时 需
  • Shell中的算术运算

    let expr bc都是在Bash shell环境中进行数学运算时我们会用到的工具 一 整数运算 let 当使用let时 变量名之前不能再添加 用法 var1 2 var2 3 let result var1 var2 echo resu
  • 一文搞懂积分不等式证明(积分证明题总结笔记3/3)

    积分证明题是考研中难度较大的板块 很多学弟学妹们希望我出一篇总结文章 故作本文 希望对大家有所帮助 本文所涉及题目 均是来自市面上常见题册 李林880 张宇1000题 汤家凤1800等 由于内容较多 故分为三部分 等式证明 点击进入 由积分
  • Qt 绘图设备,QPixmap 和QImage 相互转化

    Qt的绘图系统允许使用相同的API在屏幕和其他打印设备上进行绘制 整个绘图系统基于 QPainter QPainterDevice 和 QPaintEngine三个类 QPainter用来执行绘制的操作 QPaintDevice是一个二维空
  • ospf和mgre的综合应用

    1 R6为ISP只能配置IP地址 R1 R5的环回为私有网段 首先划分好IP地址 如下图所示 然后对各个环回和接口进行IP配置 如下面所示 对r1 r1 int l0 r1 LoopBack0 ip add 192 168 1 1 24 r
  • Mybatis-plus查看完整执行sql

    Mybatis plus查看完整执行sql application properties 文件 mybatis plus configuration log impl org apache ibatis logging stdout Std
  • Redis-Sentinel(哨兵模式),看这篇就够了哦

    文章目录 简介 启动并初始化Sentinel 初始化Sentinel服务器 替换普通Redis代码为Sentinel的专用代码 初始化 Sentinel 状态 初始化Sentinel监视的主服务器列表 创建连向主服务器的网络连接 获取主服务
  • 二进制兼容与Qt的D指针

    二进制兼容的定义 一个连接到旧版本的动态库的应用程序 无需重新编译就可以用新版本的动态库运行 则这个库被认为是二进制兼容的 一个连接到旧版本的动态库的应用程序 无需修改源码单需要重新编译后可以用新版本的动态库运行 则这个库被认为是源码兼容的
  • java版spring cloud+spring boot 直播电商 社交电子商务平台

    涉及平台 平台管理 包含自营店面 商家端 PC端 手机端 买家平台 PC端 H5 公众号 小程序 APP端 IOS Android 微服务 核心思想 分布式 微服务 云架构 模块化 原子化 持续集成 集群部署 开发模式 代码生成工具 驱动式
  • 【Java 数据结构】单链表与OJ题

    篮球哥温馨提示 编程的同时不要忘记锻炼哦 暮色降临 冲一杯咖啡 目录 1 什么是链表 2 实现一个单向非循环链表 2 1 实现前的约定 2 2 addFirst 方法 2 3 addList 方法 2 4 addIndex 方法 2 5 c
  • SpringBoot 集成积木报表

    前言 积木报表是jeecg的一款开源但代码不开源的一款自定义报表 可以基于 网页灵活调整报表的布局 样式等内容 无需编程 专为企业数据分析 报表制作而设计 降低管理人员汇总制作报表的门槛 解决各类日常管理和 汇报的难题 但是因为代码不开源所
  • SQL 入门的必读好书

    点击蓝色 有关SQL 关注我哟 加个 星标 天天与10000人一起快乐成长 最近 很多朋友来问我 有没有入门 SQL 的好书 与这些朋友聊天发现 大部分人都没有系统学过计算机专业的专修课 有从物流转行的 有从会计专业扩展的 还有从运维行业转
  • 出现“java.sql.SQLException: 无法转换为内部表示”解决方法

    现在 java sql SQLException 无法转换为内部表示 很可能是因为数据库某字段的类型出错了 比如程序将某字段当做Integer类型 而数据库存储又使用另外一种类型 不如String 建议出现这样问题的同行们认真检查一下代码
  • 软件配置管理

    第一章 1 软件配置管理用于控制变化 2 软件配置管理 Software Configuration Management SCM 是指一套管理软件开发和维护过程中所产生的各种中间软件产品的方法和规则 它是控制软件系统演变的学科 3 软件配
  • java8之lambda表达式

    java8 近期 在一个不完全的统计中 java8的普及率已经到达了近80 图 1 相比之前的java版本 下面两个是java8出现带来最大的影响 其一是极大地简化了代码的复杂度尤其是在处理集合以及接口这两个方面 除此之外 java8引入了