函数式接口
一种接口的新型设计形式:有且只有一个抽象方法
使用@FunctionalInterface可以检测接口是否是函数式接口:如果不是,则会编译失败
使用函数式接口的好处
- 使用函数式接口作为方法参数,可以传递接口的实现类
- 可以使用匿名内部类重写接口中的抽象方法
- 可以使用lambda表达式代替匿名内部类抽象接口中的抽象方法,简化代码
函数接口
接口名称 | 参数 | 返回类型 | 描述 |
Predicate | T | boolean | 用于判别一个对象 |
Consumer | T | void | 用于接受一个对象进行处理,无返回值 |
Function | T | R | 将一个对象转换为不同类型的对象 |
Supplier | None | T | 生产一个对象 |
UnaryOperator | T | T | 接受对象并返回同类型的对象 |
BinaryOperator | (T,T) | T | 接受两个同类型的对象,返回一个原类型的对象 |
函数式编程
核心概念:函数式编程作为一种编程范式,在科学领域,是一种编写程序数据结构和元素的方式,它把计算过程当作是数学函数的求值,而避免更改状态和可变数据
主要将lambda表达式延迟执行进行适当的应用
Lambda表达式
lambda表达式,可称之为闭包;也叫行为值,也叫函数式接口的实例对象。允许把函数作为一个方法的参数传递进方法中。
最明显的好处:使用lambda表达式可以简化臃肿的代码
语法格式:
lambda表达式的参数列表,位于”->“操作符的左边;
所执行的功能,即lambda体位于”->“操作符右边;
(参数)->一行输出代码 ; 或 (参数类型 参数)->{ 输出代码 };
//作为参数
(String value)->{System.out.println(value);}
//当只有一行代码时,进行完全简化,并且不需要定义参数类型,编译器会自动检测
(value)->System.out.println(value)
重要特征:
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号
- 可选的大括号:如果主体只包含了一行语句,则不需要使用大括号
- 可选的返回关键字:如果主题只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值
注意事项:
Lambda表达式主要用来定义行内执行的方法类型接口。
Lambda表达式免去了使用匿名内部类方法的麻烦,并且基于Java简单且强大的函数化的编程能力。
lambda表达式只能在方法传入函数化接口的情况下才能使用,如果接口中含有多个方法,将无法编译lambda表达式,也就是说lambda表达式需要有函数化接口的支持
as
变量作用域:
Lambda表达式只能引用标记了final的外层局部变量,也就是说不能在lambda内部修改定义在域外的局部变量,否则会编译错误。
流steam
流:可以使用声明的方式处理数据
使用lambda表达式,避免了传统的循环写法和迭代器,将操作方式作为参数传入steam对象中,交给流处理
这种处理风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如:筛选、排序、聚合等。
概念
Steam(流)是一个来自数据源的元素队列并支持聚合操作
- 元素是特定类型的对象,形成一个队列。Java中的Steam并不会存储元素,而是按需计算。
- 数据源 流的来源。可以是集合,数据,I/O channal,产生器generator等
- 聚合操作 类似SQL语句一样的操作,比如filter,map,reduce,find,match,sorted