JDK8新特性

34bcee8e9ad14dd48e9f5eb87eebd5ed.jpgLembda表达式

 

lembda表达式是一个简洁、可传递的匿名函数,实现了把代码块赋值给一个变量的功能

 

是我认为jdk1.8中最让人眼前一亮的特性(我没用过其他函数式的语言)

 

在了解表达式之前,我们先看两个概念

 

函数式接口

含有且仅含有一个抽象方法,Lembda表达式需要借助函数式接口实现。

 

通常来说我们在这个接口定义上加上@FunctionInterface注解,语义化地标注它是一个函数式接口,起到的作用和@Override相同,只起到检查作用。

 

允许对接口进行默认实现

这次更新中新增了一个default关键字,用来在接口中添加非抽象的方法实现。这个特性也被成为扩展方法。

 

在实际使用Lembda表达式的时候,我们通过表达式实现相应的接口得到接口的实现对象。我们可以直接通过这些对象调用接口中的默认实现。

 

Lembda表达式格式

Lembda表达式通过左侧的参数,右侧的表达式和中间的右箭头组成:

 

(parameter1,parameter12,...) -> {

 expression;

 ...

 return xxx;

}

可以理解为方法的另一种表现形式;

比如说这个接收a和b两个int参数,返回两数之和的方法

 

int addNum(int a,int b){

 return a + b;

}

可以写成下面这个形式

 

(int a,int b) -> {

 return a + b

}

需要注意的是:

 

参数可以为空 ()->xxx 这代表了无参方法

参数为一个值得时候,可以省略参数的括号 x->xxx

参数类型可以省略,Jdk会自动在接口中匹配相应的类型

表达式只有一行的时候不需要;,有多行的时候需要加上;

表达式可以是一个数字(直接返回这个数字),一个算式;可以是普通的一个语句(无返回,相当于void)

当表达式只有一行且最终为返回值时,return可以省略

参数的名不能和局部变量相同

表达式中直接调用的变量(不是传入的),必须是显示声明为final或事实上的final类型

自定义函数式接口并调用

我们定义一个入参是两个int类型,返回值也是int类型的方法;

 

然后添加一个将一个数加1并返回的扩展方法,使用default关键字;

 

@FunctionalInterface

interface Append {

    int append(int a, int b);

 

    default int addOne(int num) {

        return ++num;

    }

}

现在,我们使用Lambda表达式对这个接口进行实现:

 

Append append = (int a, int b) -> {

    return a + b;

};

然后我们调用这个方法,也调用接口的扩展方法

 

int num = append.append(1, 2);

int numAddOne = append.addOne(num);

System.out.println(num);//3

System.out.println(numAddOne);//4

根据上面总结的表达式格式注意事项,我们可以对表达式进行简化

 

当代码只有一行地时候可以不加分号

 

Append append = (int a, int b) -> { return a + b };

去掉参数类型,并且进一步简化右侧

 

Append append = (a, b) -> a + b;

方法调用

如果你使用的是IDEA较新版本,它会提示将它简化成另一种形式;

 

Append append = Integer::sum;

这是方法引用,在表达式中,我们可以通过类::方法的格式,直接将这个方法作为表达式的内容;

 

因此使用这种形式的时候无需指定参数,返回值等,因为这些已经确定了;

 

如果方法重载,jdk会根据传入的方法找到合适的方法

 

我们进入这个方法,发现它和我们的表达式相同

 

public static int sum(int a, int b) {

    return a + b;

}

我们还可以通过这种形式获得构造方法的调用

 

类::new

返回值就是通过合适构造方法(同样根据入参选择)创建的这个类的对象

 

Lambda表达式中变量的访问范围

外部final变量

成员变量

静态变量

需要注意,在表达式中无法访问接口的扩展方法

 

JDK自带的常用函数式接口

Predicate 判断,

boolean test(T t); 对单一参数进行判断,拓展方法可以对Predicate进行or,and的逻辑拼接,进行更复杂的逻辑判断

 

利用我们在外部设定的条件对于传入的参数进行校验并返回验证通过与否

 

Consumer 消费者

void accept(T t); 消费掉参数,啥也不返回,拓展方法可以拼接消费者链,按次序依次执行

 

接收参数并依据传递的行为应用传递的参数值

 

Function<T, R> 方法

R apoly(T t); ,该接口中有很多拓展方法,可以将多个Function拼接在一起,进行复杂的逻辑运算

执行转换操作,输入类型 T 的数据,返回 R 类型的结果

 

这三个是最重要的接口,Stream也用到这些接口,下面我强行使用这三个接口

 

    /*Predicate<T> 判断*/

    Predicate<String> stringPredicate = str -> StringUtils.isBlank(str) || "error".equalsIgnoreCase(str);

    

    /*Consumer<T>*/

    Consumer<String> stringConsumer = str -> {

        if (StringUtils.isBlank(str) || "error".equalsIgnoreCase(str)) {

            System.out.println("Consumer失败");

        }

    };

    /*Function<T,R>*/

    Function<String, String> stringStringFunction = str -> {

        if (StringUtils.isBlank(str) || "error".equalsIgnoreCase(str)) {

            return "Function失败";

        } else {

            return "Function成功";

        }

    };

    String in = "error";

    if (stringPredicate.test(in)) {

        System.out.println("Predicate失败");

    }

    stringConsumer.accept(in);

    System.out.println(stringStringFunction.apply(in));

二.Stream流

Stream使用上面说的JDK自带的函数式接口

 

Stream是一种函数式编程对集合,数组,I/O channel, 产生器generator等数据的操作方式,它有以下特点:

 

无储存,Stream本身不会储存数据

不会修改传入的数据源

惰性执行:Stream上的操作不会立即执行,而是会在真正需要的时候进行

可消费性:Stream只能被消费一次,类似迭代器,想要再次遍历,必须生成新的Stream.

在学习过程中,我发现Stream某些操作之后返回的仍然是流,而有些操作返回的确实真实的被处理之后数据,Stream的操作可以据此分为两种

 

中间操作 总是会惰式执行,调用中间操作只会生成一个标记了该操作的新stream。

结束操作 会触发实际计算,计算发生时会把所有中间操作积攒的操作以pipeline的方式执行,这样可以减少迭代次数。计算完成之后stream就会失效。

总之,把Stream看做一根水管就好啦,一开始把一根根水管拼接起来(中间操作),安装一个水龙头(结束操作),确认有水龙头之后水就依次通过水管,最后通过水龙头进入下水道(不能重复使用);

 

Collection.stream() 或者 Collection.parallelStream() 来创建一个串行Stream或者并行Stream。

 

常用的Stream方法

 

中间操作

sorted排序

Stream<T> sorted();

Stream<T> sorted(Comparator<? super T> comparator);

 

这是一个有状态的操作

 

用法 作用

sorted() 自然排序

sorted(Comparator.reverseOrder()) 自然逆向排序

sorted(Comparator.comparing(Student::getAge)) 通过某些元素排序

sorted(Comparator.comparing(Student::getAge).reversed()) 通过某些元素逆向排序

Comparator是比较器

 

map元素操作

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

用于对每个元素进行操作,并且将处理后的Stream返回

例如map(i->i*2)将所有数据进行平方操作

 

filter过滤

Stream<T> filter(Predicate<? super T> predicate);

入参为Predicate,lembda表达式返回值是boolean;

如果表达式为flase,则剔除数据,只留符合条件的

过滤是中间操作:Stream<Integer> integerStream = intList.stream().filter(i -> i > 4);

 

limit限制

Stream<T> limit(long maxSize);

限制数据的数量,这是一个有状态的短路的操作。

 

distinct去重

Stream<T> distinct();

去除重复的操作,这是一个有状态的操作

 

结束操作

forEach迭代

void forEach(Consumer<? super T> action);

入参是Consumer,表达式不需要返回值,方法本身返回值void,所以是结束操作

常用的方法是forEach(System.out::println);

 

collect存入容器

<R, A> R collect(Collector<? super T, A, R> collector);

将数据存入一个Collection或Map

 

toArray存入数组

Object[] toArray();

将结果存入一个数组中

 

count计数

long count();

计算流中元素的数量

 

max 和 min

Optional<T> min(Comparator<? super T> comparator);

Optional<T> max(Comparator<? super T> comparator);

根据一个比较器找到最大或最小元素

 

anyMatch allMatch noneMatch 匹配

boolean anyMatch(Predicate<? super T> predicate);三个都一样

是否至少有一个元素匹配

是否每一个元素都匹配

是否没有元素匹配

 

findFirst findAny 查找

Optional<T> findFirst();

查找第一个元素

查找随机的一个元素

 

Stream常用代码

List转Map

 

Map<Integer, A> aMap = aList.stream().col

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/82387.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS核心使用

CSS核心使用 box-sizingbox-shdowtext-shadowpositionwriting-mode box-sizing 定义计算一个元素的总高度和总宽度. 属性值 content-box 默认值,width 内容宽度,height内容的高度border-box 宽度和高度包含内容,内边距和边框 widthborderpadding内容宽度, heightborderpaddi…

测试进阶知识之零日攻击的发现和防御

零日攻击是指针对软件或系统中未公开&#xff08;或未被开发者知晓&#xff09;的漏洞进行的攻击。这些漏洞被称为零日漏洞&#xff0c;因为在被公开之前&#xff0c;它们对开发者或安全研究人员来说是未知的&#xff0c;所以没有足够的时间进行防御或修复。 发现零日漏洞 发…

启动YOLO进行图片物体识别

查看官方文档YOLO: Real-Time Object Detection 这些是一些模型的对比&#xff0c;显示了YOLO的优势&#xff0c;继续往下面看 CoCoData set 是一个数据库&#xff0c;用来训练模型&#xff0c;这里面有丰富的物体检测&#xff0c;分割数据集&#xff0c;图像经过了精确的segm…

Pikachu Burte Force(暴力破解)

一、Burte Force&#xff08;暴力破解&#xff09;概述 ​ “暴力破解”是一攻击具手段&#xff0c;在web攻击中&#xff0c;一般会使用这种手段对应用系统的认证信息进行获取。 其过程就是使用大量的认证信息在认证接口进行尝试登录&#xff0c;直到得到正确的结果。 为了提高…

Jenkins List Git Branches插件 构建选择指定git分支

List Git Branches Parameter | Jenkins pluginAdds ability to choose from git repository revisions or tagshttps://plugins.jenkins.io/list-git-branches-parameter/ 1、安装组件 List Git Branches 2、验证功能 1&#xff09;新建任务 2&#xff09;新增构建参数 3&…

JavaSE List

目录 1 预备知识-泛型(Generic)1.1 泛型的引入1.2 泛型类的定义的简单演示 1.3 泛型背后作用时期和背后的简单原理1.4 泛型类的使用1.5 泛型总结 2 预备知识-包装类&#xff08;Wrapper Class&#xff09;2.1 基本数据类型和包装类直接的对应关系2.2 包装类的使用&#xff0c;装…

【教程】微信小程序导入外部字体详细流程

前言 在微信小程序中&#xff0c;我们在wxss文件中通过font-family这一CSS属性来设置文本的字体&#xff0c;并且微信小程序有自身支持的内置字体&#xff0c;可以通过代码提示查看微信小程序支持字体&#xff1a; 这些字体具体是什么样式可以参考&#xff1a; 微信小程序--字…

ATF(TF-A) SPMC威胁模型-安全检测与评估

安全之安全(security)博客目录导读 ATF(TF-A) 威胁模型汇总 目录 一、简介 二、评估目标 1、数据流图 三、威胁分析 1、信任边界 2、资产 3、威胁代理 4、威胁类型 5、威胁评估 5.1 端点在直接请求/响应调用中模拟发送方或接收方FF-A ID 5.2 篡改端点和SPMC之间的…

基于element-ui的年份范围选择器

基于element-ui的年份范围选择器 element-ui官方只有日期范围和月份范围选择器&#xff0c;根据需求场景需要&#xff0c;支持年份选择器&#xff0c;原本使用两个分开的年份选择器实现的&#xff0c;但是往往有些是不能接受的。在网上找了很多都没有合适的&#xff0c;所以打…

【内网穿透】公网远程访问本地硬盘文件

公网远程访问本地硬盘文件【内网穿透】 文章目录 公网远程访问本地硬盘文件【内网穿透】前言1. 下载cpolar和Everything软件3. 设定http服务器端口4. 进入cpolar的设置5. 生成公网连到本地内网穿透数据隧道 总结 前言 随着云概念的流行&#xff0c;不少企业采用云存储技术来保…

Linux 信号相关

int kill(pid_t pid, int sig); -功能&#xff1a;给某个进程pid 发送某个信号 参数sig可以使用宏值或者和它对应的编号 参数pid&#xff1a; >0 &#xff1b;将信号发给指定的进程 0&#xff1b;将信号发送给当前的进程组 -1&#xff1b;发送给每一个有权限接受这个信号的…

【面试必刷TOP101】删除链表的倒数第n个节点 两个链表的第一个公共结点

目录 题目&#xff1a;删除链表的倒数第n个节点_牛客题霸_牛客网 (nowcoder.com) 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 题目&#xff1a;两个链表的第一个公共结点_牛客题霸_牛客网 (nowcoder.com) …

【C++ 学习 ㉑】- 详解 map 和 set(上)

目录 一、C STL 关联式容器 二、pair 类模板 三、set 3.1 - set 的基本介绍 3.2 - set 的成员函数 3.1.1 - 构造函数 3.1.2 - 迭代器 3.1.3 - 修改操作 3.1.4 - 其他操作 四、map 4.1 - map 的基本介绍 4.2 - map 的成员函数 4.2.1 - 迭代器 4.2.2 - operator[] …

go语言---锁

什么是锁呢&#xff1f;就是某个协程&#xff08;线程&#xff09;在访问某个资源时先锁住&#xff0c;防止其它协程的访问&#xff0c;等访问完毕解锁后其他协程再来加锁进行访问。这和我们生活中加锁使用公共资源相似&#xff0c;例如&#xff1a;公共卫生间。 死锁 死锁是…

Ubuntu安装中文拼音输入法

ubuntu安装中文拼音输入法 ubuntu版本为23.04 1、安装中文语言包 首先安装中文输入法必须要让系统支持中文语言&#xff0c;可以在 Language Support 中安装中文语言包。 添加或删除语音选项&#xff0c;添加中文简体&#xff0c;然后会有Applying changes的对话框&#x…

vue 把echarts封装成一个方法 并且从后端读取数据 +转换数据格式 =动态echarts 联动echarts表

1.把echarts 在 methods 封装成一个方法mounted 在中调用 折线图 和柱状图 mounted调用下边两个方法 mounted(){//最早获取DOM元素的生命周期函数 挂载完毕console.log(mounted-id , document.getElementById(charts))this.line()this.pie()},methods里边的方法 line() {// …

在Android studio 创建Flutter项目运行出现问题总结

在Android studio 中配置Flutter出现的问题 A problem occurred configuring root project ‘android’出现这个问题。解决办法 首先找到flutter配置的位置 在D:\xxx\flutter\packages\flutter_tools\gradle位置中的flutter.gradle buildscript { repositories { googl…

3D目标检测框架 MMDetection3D环境搭建 docker篇

本文介绍如何搭建3D目标检测框架&#xff0c;使用docker快速搭建MMDetection3D的开发环境&#xff0c;实现视觉3D目标检测、点云3D目标检测、多模态3D目标检测等等。 需要大家提前安装好docker&#xff0c;并且docker版本> 19.03。 1、下载MMDetection3D源码 https://gith…

《Linux运维总结:Centos7.6之OpenSSH7.4升级版本至9.4》

一、环境信息 操作系统&#xff1a;Centos7.6.1810 OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 如下图所示&#xff1a; 注意&#xff1a;升级后由于加密算法的区别&#xff0c;低版本的SSH工具可能无法连接&#xff0c;建议改用Xshell7或SecureCRT9.0以上版本。 二、注意事项 1、检…

Centos安装显卡

1、安装基础环境 yum -y install epel-release yum -y install gcc kernel-devel kernel-headers 2.对应内核版本 yum info kernel-devel kernel-headers Cat /proc/version 3、yum安装版本不对应。则去官网手动下载 离线安装对应的rpm&#xff1a; https://pkgs.org/dow…