JAVA8之函数式接口
由于JDK8已经发布一段时间了,也开始逐渐稳定,未来使用JAVA语言开发的系统会逐渐升级到JDK8,因为为了以后工作需要,我们有必要了解JAVA8的一些新的特性。JAVA8相对JAVA7最重要的一个突破是引入了函数式接口(包在java.util.function),下面我们来介绍下相关接口
FunctionalInterface注解
JDK8新引入的用于标识函数式接口的一个注解,如注释中所说明的,他是一个接口的信息注解,用于标识接口是函数式接口。被该注解标识的接口必须满足有且仅有一个抽象方法,当然继承自Object的公有方法不计算在内,如果有一个抽象方法需要绕过自己实现default。
@FunctionalInterface
public interface Func {
void run();
}
被FunctionalInterface注解的函数式接口可以声明为方法参数,被lambda表达式和函数引用表达式替换,当函数式接口多重继承其他接口,其他接口有相同(包括泛型)的方法签名,那么仍视该接口为函数式接口
public class TestFunctionalInterface{
public void run() {
System.out.println("TestFunctionalInterface is invoked");
}
public void testInvoke(Func func){
func.run();
}
public static void main(String[] args){
TestFunctionalInterface testInter = new TestFunctionalInterface();
testInter.testInvoke(()->System.out.println("hello World"));
testInter.testInvoke(testInter::run);
}
}
JDK8定义的函数式接口在java.util.function包,主要包含Function、Predicate、Supplier、Consumer和*Operator等几类,下面对这几类进行说明
1、Function
函数式接口,接受一个输入参数生成一个输出结果,
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
} default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
} static <T> Function<T, T> identity() {
return t -> t;
}
}
apply方法
接受一个参数把它作为参数传递给一个方法,并返回结果,即$R=Function(T)$
compose方法
把参数传给before函数,并把函数返回结果作为参数再传给当前函数,返回计算结果
andThen方法
把参数传给当前函数,并将函数计算结果作为参数传给after函数,返回after函数的计算结果
identity
返回一个函数,该函数直接返回入参
public class FunctionTest {
public static void main(String[] args){
Function<Integer,Integer> self = Function.identity();
Function<Integer,Integer> incr = x->x+1;
Function<Integer,Integer> multi = x->x*2;
int x = 2;
System.out.println(self.apply(x));
System.out.println(incr.compose(multi).apply(x));
System.out.println(incr.andThen(multi).apply(x));
}
}
由于函数式接口可以接受函数作为返回结果,利用这个特性我们还可以定义复杂的计算
public class FunctionTest {
public static void main(String[] args){
Function<Integer,Function<Integer,Integer>> func2 = x-> y->x+y;
System.out.println("x = 1, y = 2 , x+y = "+func2.apply(1).apply(2));
}
}
和Function接口类似的函数式接口还有
BiFunction:二元函数,接受两个入参,返回一个结果,支持apply、andThen方法
DoubleFunction: 只处理double类型入参的一元函数
IntFunction: 只处理int型入参的一元函数
LongFunction: 只处理long类型入参的一元函数
ToDoubleFunction: 返回double类型的一元函数,支持applyAsDouble方法,函数不必一定返回double类型,但必须可转为double类型
ToDoubleBiFunction: 返回double类型的二元函数
ToIntFunction: 返回Int类型的一元函数
ToIntBiFunction: 返回int类型的二元函数
ToLongFunction: 返回int类型的一元函数
ToLongBiFunction: 返回long类型的二元函数
DoubleToIntFunction: 接受double类型入参返回int的一元函数
DoubleToLongFunction: 接受double类型入参返回Long的一元函数
IntToDoubleFunction: 接受int入参返回Double的一元函数
LongToDoubleFunction: 接受long入参返回double的一元函数
LongToIntFunction: 接受Long入参返回int的一元函数
2、Predicate
特殊的Function函数式接口,根据传入的一个参数推导真假值,等价于返回值为boolean的特殊Function,阅读JDK源码可知该函数式接口还提供了and,or和negative谓词逻辑的默认实现
@FunctionalInterface
public interface Predicate<T> { boolean test(T t); default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
} default Predicate<T> negate() {
return (t) -> !test(t);
} default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
} static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
3、Supplier
生成器函数,没有入参,只声明了返回值,在流式计算中用于生成数据
@FunctionalInterface
public interface Supplier<T> { T get();
}
其他类似的Supplier接口
BooleanSupplier:返回值为boolean类型
DoubleSupplier:返回值为double类型
IntSupplier:返回值为Int类型
LongSupplier:返回值为long类型
4、Consumer
对传入的参数进行处理不需要返回值的函数式接口,该接口提供了一个andThen默认实现
@FunctionalInterface
public interface Consumer<T> { void accept(T t); default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
其他类似的Consumer接口
BiConsumer: 接受两个参数无返回值的函数
DoubleConsumer: 入参为double类型无返回值的函数
IntConsumer: 入参为Int类型无返回值的函数
LongConsumer: 入参为Long类型无返回值的参数
ObjDoubleConsumer: 接受一个泛型参数和Double类型入参无返回值的函数
ObjIntConsumer: 接受一个泛型参数和Int类型入参无返回值的函数
ObjLongConsumer: 接受一个泛型参数和Long类型入参无返回值的函数
5、Operator
算子,特殊的函数式接口,入参与返回结果类型一致,因此只需声明一个泛型参数即可,超类为对应的Function,在JAVA8中通常作为函数式接口的补充,主要包括UnaryOperator和BinaryOperator,分别对应单元算子和二元算子
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> { static <T> UnaryOperator<T> identity() {
return t -> t;
}
}
@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> { public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
} public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
}
}
阅读JDK8源码可知UnaryOperator只包含一个返回入参的成员方法,二元算子BinaryOperator提供了两个默认static方法的实现maxBy,minBy分别返回两个入参的较大值、较小值
其他的Operator接口:
LongUnaryOperator:类型为Long的一元算子,成员方法包括applyAsLong,compose,andThen,identity
IntUnaryOperator: 类型为Int的一元算子,成员方法包括applyAsInt,compose,andThen,identity
DoubleOperator: 类型为Double的一元算子,成员方法包括applyAsDouble,compose,andThen,identity
LongBinaryOperator: 类型为Long的二元算子
IntBinaryOperator: 类型为Int的二元算子
DoubleBinaryOperator: 类型为Double的二元算子
JAVA8之函数式接口的更多相关文章
- java8的函数式接口
函数式接口 就是在java8里允许你为一个接口(只有一个实现的,声明为FunctionalInterface注解的)实现一个匿名的对象,大叔感觉它与.net平台的委托很类似,一个方法里允许你接收一个方 ...
- [译]Java8的函数式接口
Java8引入了 java.util.function 包,他包含了函数式接口,具体的描述在以下api说明文档中: 函数式接口为lambda表达式和方法引用提供目标类型.每个函数式接口有一个单独的抽象 ...
- Java8 Functional(函数式接口)
Functional 函数式(Functional)接口 只包含一个抽象方法的接口,称为函数式接口. 你可以通过 Lambda 表达式来创建该接口的对象.(若 Lambda 表达式抛出一个受检异常(即 ...
- java8 常用函数式接口
public static void main(String[] args) { // TODO Auto-generated method stub //函数式接口 Function<Inte ...
- 乐字节-Java8核心特性实战之函数式接口
什么时候可以使用Lambda?通常Lambda表达式是用在函数式接口上使用的.从Java8开始引入了函数式接口,其说明比较简单:函数式接口(Functional Interface)就是一个有且仅有一 ...
- java8学习之Supplier与函数式接口总结
Supplier接口: 继续学习一个新的函数式接口--Supplier,它的中文意思为供应商.提供者,下面看一下它的javadoc: 而具体的方法也是相当的简单,就是不接受任何参数,返回一个结果: 对 ...
- java代码之美(14)---Java8 函数式接口
Java8 函数式接口 之前写了有关JDK8的Lambda表达式:java代码之美(1)---Java8 Lambda 函数式接口可以理解就是为Lambda服务的,它们组合在一起可以让你的代码看去更加 ...
- java代码(14) --Java8函数式接口
Java8函数式接口 之前有关JDK8的Lambda表达式 Java代码(1)--Java8 Lambda 函数式接口可以理解就是为Lambda服务的,它们组合在一起可以让你的代码看去更加简洁 一.概 ...
- Java8的新特性--函数式接口
目录 函数式接口 什么是函数式接口 函数式接口的使用 Java8内置的四大核心函数式接口 一.Consumer:消费型接口(void accept(T t)) 二.Supplier:供给型接口(T g ...
随机推荐
- Mysql模糊查询like效率,以及更高效的写法
在使用msyql进行模糊查询的时候,很自然的会用到like语句,通常情况下,在数据量小的时候,不容易看出查询的效率,但在数据量达到百万级,千万级的时候,查询的效率就很容易显现出来.这个时候查询的效率就 ...
- ajax return 的问题
平时都是在AJAX里执行逻辑,实然想到能不能return返回数据呢? ajax 是异步请求,return拿值得时候 ajax并没有取到值,所以是undefind. 需要把ajax的请求方式改为同步 v ...
- hello2 source anaylis
首先,我们先来看一看这一段的整体代码, 代码如下: @WebServlet("/greeting") public class GreetingServlet extends Ht ...
- js实现复制内容到剪切板,兼容pc和手机端,支持Safari浏览器
Javascript原生有一些事件:copy.paste.cut, 这些事件可以作用的目标元素: 能获得焦点的元素 (如contentEditable内容能编辑或者可以选中的元素),或者是<bo ...
- web文件上传
文件上传的步骤: 1.目前Java文件上传功能都是依靠Apache组织的commons-io, fileupload两个包来实现的: 2. http://commons.apache.org/下载io ...
- 【 剑指Offer 1 】数据结构
数据结构是技术面试中的重点,总结以下几种常见的必须熟练掌握数据结构. 数组 字符串 链表 树 栈和队列 数组和字符串是两种最基本的数据结构,连续内存: 链表和树是面试中出现频率最高的: 栈与递归密切相 ...
- Docker Kubernetes YAML文件常用指令
YAML文件常用指令 配置文件说明: 定义配置时,指定最新稳定版API(当前为v1). 配置文件应该存储在集群之外的版本控制仓库中.如果需要,可以快速回滚配置.重新创建和恢复. 应该使用YAML格式编 ...
- react-router 4.0(一)
import React from 'react'; import ReactDOM from 'react-dom' import {Link,Route,HashRouter} from 'rea ...
- 微信小程序wepy开发,$apply()不能更新页面数据的情况
例如userinfo信息获取到后,$apply()更新后还是没有在页面中显示数据 已发现的原因: 当data中没有定义userinfo时,会发生这样的问题
- (转载)Unity学习笔记:关于Dropdown的学习
今天组长让我写一个界面,其中用到了下拉条,我的印象还停留在以前的NGUI有现成的组件,但是uGUI没有的那阶段,组长跟我说uGUI现在也有了,研究了一下,发现real方便哦,今天就来简单说一下用法吧. ...