Java8 lambda函数式编程
Lambda 表达式是 Java SE8 推出的新功能,也是Java第一次引入函数式编程的尝试。
Lambda表达式格式
Lambda 表达式可以看做是一种匿名函数,但是它没有访问修饰符、返回值和名字。Lambda表达式由两部分构成,形式参数和方法体,中间用“->”符号分隔。其中的形式参数类型能够进行自动推断,可以不写。当然在某些特殊情况下,形参类型也是不可缺少的。方法体可以是简单的表达式或者代码块,下面是一些例子:
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
要理解Lambda表达式,首先要了解一种特殊的接口:函数式接口。什么是函数式接口呢?简单来说就是只包含一个抽象方法的接口。Java标准库中的java.lang.Runnable和java.util.Comparator就是典型的函数式接口。对于函数式接口,我们就可以使用Lambda表达式来代替用传统匿名类来创建实例对象。
java.util.function包
在Java SE8之前标准库中的函数式接口并不多。JavaSE8增加了java.util.function包,里面都是可以在开发中只用的函数式接口。我们也可以自定义一个函数式接口,但最好在接口上使用@FunctionalInterface注解标明这是一个函数式接口,以免团队其它成员错误地往接口添加新的方法,当然java.util.function包中的所有接口都添加了@FunctionalInterface注解。
函数式接口
我们以Runnable接口为例,用传统匿名类的方式创建一个线程:
public void runThread() {
new Thread(new Runnable() {
public void run() {
System.out.println("Run!");
}
}).start();
}
上面传统匿名类方式中,我们可以看到,我们需要new一个接口名称,接口内部还要附带这个接口抽象方法的实现。而如果我们使用Lambda表达式,则代码非常简洁:
public void runThreadUseLambda() {
new Thread(() -> {
System.out.println("Run!");
}).start();
}
通过上面代码我们可以看到,Lambda表达式在两方面做了简化:
首先不需要声明Runnable接口,因为这可以通过上下文推断出来
其次不需要再写一个run方法的实现,因为函数式接口中只有一个方法
---------------------
使用场景
场景:有个User的List,需要将所有的用户ID取出来。
List<Integer> userIds = users.stream().map(u -> u.getId()).collect(Collectors.toList());
1
场景:有个User的List,需要将所有的用户ID取出来,还得注意去重
List<Integer> userIds = users.stream().map(u -> u.getId()).distinct().collect(Collectors.toList());
1
场景:有个User的List,需要将其放到HashMap里,key为用户ID,value为该User
Map<Integer, User> userMap = users.stream().collect(Collectors.toMap(User :: getId, u -> u));
1
场景:有个User的List,需要将其放到HashMap里,key为用户ID,value为用户名称
Map<Integer, String> userMap = users.stream().collect(Collectors.toMap(User :: getId, u -> u.getName()));
1
场景:有个User的List,需要将其放到HashMap里,key为用户ID,value为该User。User可能会重复,也就是ID会重复。按照上面的做法会导致如下错误:
Exception in thread "main" java.lang.IllegalStateException: Duplicate key 123456
1
/**
* 需要指定在key重复时选择保留旧值还是新值
*/
Map<Integer, User> userMap = users.stream().collect(Collectors.toMap(User :: getId, u -> u, (oldV, newV) -> newV));
1
场景:有个User的List,需要按照id的大小进行排序
List<User> users = new ArrayList<User>();
users.sort((u1, u2) -> u1.getId().compareTo(u2.getId()));
---------------------
常用方法
stream()、将集合变成了流,
filter、过滤到我们所需要的,
collect(Collectors.toList())、将得到的流对象转换为集合。 Collect()即为收集器用来将经过筛选、映射的流进行最后的整理
groupingBy() 分组
/joining()连接流中每个元素的toString方法生成的字符串
/reducing()是针对单个值的收集,其返回结果不是集合家族的类型,而是单一的实体类T
/collectingAndThen()转换函数返回的类型
/Counting()计算流中个数/
SummingInt()对流中元素的一个整数属性求和
/averagingInt()计算流中元素integer属性的平均值
maxBy()比较器选出的最大元素的optional,如果为空返回的是Optional.empty()
minBy()比较器选出的最小元素的optional,如果为空返回的是Optional.empty()
Collectors的常用封装有:toList()/toMap()/toCollection()/toSet()
map() 映射
distinct()去重
limit(3)截取流的前N个元素
skip(3)跳过流的前n个元素
equels() 比较
anyMatch()判断流中是否匹配任意元素
allMatch()判断流中是否匹配任意元素
noneMatch()判断流中是否未匹配所有元素
findAny()从流中获取任意元素,返回一个Optional类型的元素
Optional是Java8新加入的一个容器,这个容器只存1个或0个元素,它用于防止出现NullpointException,它提供如下方法:
isPresent()
判断容器中是否有值。
ifPresent(Consume lambda)
容器若不为空则执行括号中的Lambda表达式。
T get()
获取容器中的元素,若容器为空则抛出NoSuchElement异常。
T orElse(T other)
获取容器中的元素,若容器为空则返回括号中的默认值。
---------------------
reduce()归约 是将集合中的所有元素经过指定运算,折叠成一个元素输出
数值流采用reduce进行数值操作会涉及到基本数值类型和引用数值类型之间的装箱、拆箱操作,因此效率较低。
当流操作为纯数值操作时,使用数值流能获得较高的效率。
StreamAPI提供了三种数值流:IntStream、DoubleStream、LongStream,也提供了将普通流转换成数值流的三种方法:mapToInt、mapToDouble、mapToLong。
每种数值流都提供了数值计算函数,如max、min、sum等
forEach()循环
sort()排序
sorted()排序
Comparator()排序
详细使用参考:https://blog.csdn.net/u010425776/article/details/52344425
转载于:https://www.cnblogs.com/Bkxk/p/11169833.html
Java8 lambda函数式编程相关推荐
- Java8之函数式编程
Java8之函数式编程 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性. Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中). 使用 Lambda ...
- lambda 函数式编程_Java 8 Lambda表达式的函数式编程– Monads
lambda 函数式编程 什么是monad ?: monad是一种设计模式概念,用于大多数功能编程语言(如lisp)或现代世界的Clojure或Scala中. (实际上,我会从scala复制一些内容. ...
- JAVA8之函数式编程Supplier接口和Consumer接口
JAVA8之函数式编程Supplier接口和Consumer接口 一. Supplier接口 顾名思义,这是一个供应商,提供者.就如一个工厂一样.该类的源码如下: package java.ut ...
- Java8新特性——Lambda函数式编程
前言 Java一直是一门面向对象语言,万事万物皆对象,如果想要调用一个函数,函数必须属于一个类或对象,然后在使用类或对象进行调用. 在Java中,"."表示调用某个对象的方法 ...
- java8函数式编程 视频_快速掌握Java8 Stream函数式编程技巧
函数式编程优势"函数第一位",即函数可以出现在任何地方. 可以把函数作为参数传递给另一个函数,还可以将函数作为返回值. 让代码的逻辑更清晰更优雅. 减少了可变量(Immutable ...
- Lambda函数式编程
作者: 西魏陶渊明 博客: https://blog.springlearn.cn/ 西魏陶渊明 莫笑少年江湖梦,谁不少年梦江湖 Java8所有的新特性基本基于函数式编程的思想,函数式编程给Java带 ...
- Java8之Lambda函数式编程(一)
Java8中,最重要且最实用的莫过于Lambda表达式和Stream流式编程了.它改变了以往传统的编程方式,更高效.更简洁.并且代码更具有可读性.现在基本所有的大型互联网公司很早就摒弃JDK.1.7而 ...
- [一] java8 函数式编程入门 什么是函数式编程 函数接口概念 流和收集器基本概念...
本文是针对于java8引入函数式编程概念以及stream流相关的一些简单介绍 什么是函数式编程? java程序员第一反应可能会理解成类的成员方法一类的东西 此处并不是这个含义,更接近是数学上的函数 ...
- java中函数是什么_[一] java8 函数式编程入门 什么是函数式编程 函数接口概念 流和收集器基本概念...
本文是针对于java8引入函数式编程概念以及stream流相关的一些简单介绍 什么是函数式编程? java程序员第一反应可能会理解成类的成员方法一类的东西 此处并不是这个含义,更接近是数学上的函数 看 ...
最新文章
- cmd开无线服务器,使用cmd命令开启wifi
- linux笔记本上安装了双显卡驱动(intel+nvidia)
- 计算机学机械制图吗,机械制图与计算机绘图(少学时·任务驱动模式)
- 【Android 进程保活】oom_adj 值 ( oom_adj 值对应的进程优先级 | oom_adj 值动态改变 | 进程保活优化方向 )
- cocos2d-x 关于tilemap滚动时黑线闪动的问题
- 使用solr的DIHandler 构建mysql大表全量索引,内存溢出问题的解决方法
- c语言编制编程语言,C语言CGI编程入门(一)
- java concurrent int_java.util.concurrent.AtomicInteger
- SQL文档阅读笔记-对水平分区和垂直分区理解
- 驱动中的资源共享和临界代码保护
- 带你玩转Visual Studio(八)——带你跳出坑爹的Runtime Library坑
- 精灵骑士二觉_守护者二觉转职分析 精灵骑士二觉能有多强
- Java正则表达式语法规则(具体)
- NCL做一个简单的EOF分析例子
- CVPR 2021 Involution: Inverting the Inherence of Convolution for Visual Recognition
- 图形界面上的任意形状图形按钮
- 大一期末项目:学生管理系统
- 苹果Mac系统彻底关闭开机声音duang~
- 简单教学管理系统画E-R关系图
- UNIX TIMESTAMP 与 TIME 之间的转换
热门文章
- Left join与简单多表查询
- dup和dup2以及cat函数函数
- SpringBoot测试时出现Whitelabel Error Page
- html5.js让IE(包括IE6)支持HTML5元素方法
- 【Let‘s Go】Go语言入门篇
- Java中抽象类、接口、父类直接的区别与联系
- docker搭建nacos1.4.1挂载文件并实现mysql持久化
- 汇编语言位向量(位映射)
- 汇编语言整数加减法示例
- 【译】Jumping into Solidity —The ERC721 Standard (Part 1)