Java之函数式接口@FunctionalInterface详解

函数式接口的定义

在java8中,满足下面任意一个条件的接口都是函数式接口:

1、被@FunctionalInterface注释的接口,满足@FunctionalInterface注释的约束。

2、没有被@FunctionalInterface注释的接口,但是满足@FunctionalInterface注释的约束

@FunctionalInterface注释的约束:

1、接口有且只能有个一个抽象方法,只有方法定义,没有方法体

2、在接口中覆写Object类中的public方法,不算是函数式接口的方法。

比如:

@FunctionalInterface
interface FunctionalInterfaceTest {
String getInfo(String input);
}

函数式接口的实例

  1. lambda表达式
  2. 方法的引用
  3. 已有构造器或方法的引用
public class Main {

    public static void main(String[] args)
throws ClassNotFoundException,
IllegalAccessException,
InstantiationException,
NoSuchMethodException,
InvocationTargetException, NoSuchFieldException {
/**
* 1、lambda表达式
* 这种形式最为直观,lambda表达式,接收一个String类型的参数,返回一个String类型的结果。
* 完全符合函数式接口FunctionInterfaceTest的定义
*/
FunctionalInterfaceTest fiTest1 = str -> str + " copy";
/**
* 2、Main方法当中的functionalInterfaceTestMethod方法接收一个参数,返回一个结果。符合函数式接口
* FunctionInterfaceTest的定义。
* 函数式接口只是定义了个方法的约定(接收一个String类型的参数,返回一个String类型的结果),
* 而对于方法内部进行何种操作则并没有做任何的限制。在这点上,跟java以前的版本中的实现类与接口之间的
* 关系很类似。不同的是,函数式接口更偏重于计算过程,约束了一个计算过程的输入和输出。
*/
FunctionalInterfaceTest fiTest2 = Main::functionalInterfaceTestMethod;
/**
* 3、构造方法引用
* 构造函数的结构:接收输入参数,然后返回一个对象。这种约束跟函数式接口的约束很像。
* 所以只要“输入参数类型”与“输出参数类型”跟FunctionInterfaceTest中的方法约束相同,
* 就可以创建出FunctionInterfaceTest接口的实例,如下,String的构造方法中有
* new String(str)的构造方法,所以可以得到实例。
* 这里存在一个类型推断的问题,JDK的编译器已经帮我们自动找到了只有一个参数,且是String类型的构造方法。
* 这就是我们直接String::new,没有指定使用哪一个构造方法,却可以创建实例的原因
*/
FunctionalInterfaceTest fiTest3 = String::new; System.out.println(useFunctionalInterface("Hello World!", fiTest1));
System.out.println(useFunctionalInterface("Hello World!", fiTest2));
System.out.println(useFunctionalInterface("Hello World!", fiTest3));
System.out.println(useFunctionalInterface("Hello World!", str -> str + " created by lambda in the context"));
/**
输出:
Hello World! copy
Hello World! copy 2 by reference
Hello World!
Hello World! created by lambda in the context
*/
} public static String functionalInterfaceTestMethod(String str) {
return str + " copy 2 by reference";
} public static String useFunctionalInterface(String str, FunctionalInterfaceTest fiT) {
return fiT.getInfo(str);
}
}

常用的封装好的函数式接口

分别为Function<T, R>, Cosumer<T>, Predicate<T>, Supplier<T>

/**
* 常用的函数式接口主要有四种类型,是通过其输入和输出的参数来进行区分的。定义了编码过程中主要的使用场景。
Function<T,R>
接收一个T类型的参数,返回一个R类型的结果 Consumer<T>
接收一个T类型的参数,不返回值 Predicate<T>
接收一个T类型的参数,返回一个boolean类型的结果 Supplier<T>
不接受参数,返回一个T类型的结果
*/
Function<String, String> add_postfix = str -> str + "postfix";
Consumer<String> print_string = System.out::println;
Predicate<Integer> judge_positive = n -> n > 0;
Supplier<String> supplier = () -> "supply";
List<String> list = Arrays.asList("adfsg", "sdafef", "", "s", "231243", "hgjrepjrg");
list.stream()
.map(str -> str + "1")
.filter(str -> str.length() > 2)
.sorted((str1, str2) -> str2.compareTo(str1))
.forEach(System.out::println);
/**
输出:
sdafef1
hgjrepjrg1
adfsg1
2312431
1234dfgh
*/

此外,对于多参数的情况,Java还封装了BiFunction<T, U, R>, BiConsumer<T, U>, BiPredicate<T, U>。

// 由于java不能返回多个参数,所以没有BiSupplier
BiFunction<String, String, String> combine_string = (str1, str2) -> str1 + str2;
BiConsumer<String, String> print_two_string = (str1, str2) -> System.out.println(str1 + str2);
BiPredicate<String, String> str_equal = String::equals;
int bif_result = biFunctionTestMethod("abs", "pdf", (str1, str2) -> str1.length() + str2.length());
biConsumerTestMethod("1234", "dfgh", (str1, str2) -> System.out.println(str1 + str2));
boolean bip_result_1 = biPredictTestMethod("abc", "abc", str_equal),
bip_result_2 = biPredictTestMethod("abc", "def", str_equal);
System.out.println(bif_result);
System.out.println(bip_result_1);
System.out.println(bip_result_2);
/*
输出:
6
true
false
*/

在此之外,还有compose和andThen方法,其本质就是数学当中的符合函数,唯一的区别:对于函数\(f(x),g(x)\),compose等价于\(f(g(x))\),andThen等价于\(g(f(x))\),就是执行顺序不同而已。

// compose 和 andThen
Function<String, String> compose_function = ((Function<String, String>) (str -> str + "abc")).compose((Function<String, String>) (str -> str + str.length()));
System.out.println("Compose function: " + compose_function.apply("Hello World! "));
Function<String, String> andThen_function = ((Function<String, String>) (str -> str + "abc")).andThen((Function<String, String>) (str -> str + str.length()));
System.out.println("AndThen function: " + andThen_function.apply("Hello World! "));
// Bicosumer, cosumer, bifunction 都有类似功能 // BiPredicate, Predicate 的 and, or, negate
System.out.println(str_equal.negate().test("a", "a")); // false
System.out.println(judge_positive.and(n -> n > 2).test(5)); // true
System.out.println(judge_positive.or(n -> n < -1).test(-10)); // true

源码

Function.java

/**
* Represents a function that accepts one argument and produces a result.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #apply(Object)}.
*
* @param <T> the type of the input to the function
* @param <R> the type of the result of the function
*
* @since 1.8
*/
@FunctionalInterface
public interface Function<T, R> { /**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t); /**
* Returns a composed function that first applies the {@code before}
* function to its input, and then applies this function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of input to the {@code before} function, and to the
* composed function
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before}
* function and then applies this function
* @throws NullPointerException if before is null
*
* @see #andThen(Function)
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
} /**
* Returns a composed function that first applies this function to
* its input, and then applies the {@code after} function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of output of the {@code after} function, and of the
* composed function
* @param after the function to apply after this function is applied
* @return a composed function that first applies this function and then
* applies the {@code after} function
* @throws NullPointerException if after is null
*
* @see #compose(Function)
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
} /**
* Returns a function that always returns its input argument.
*
* @param <T> the type of the input and output objects to the function
* @return a function that always returns its input argument
*/
static <T> Function<T, T> identity() {
return t -> t;
}
}

Consumer.java

/**
* Represents an operation that accepts a single input argument and returns no
* result. Unlike most other functional interfaces, {@code Consumer} is expected
* to operate via side-effects.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #accept(Object)}.
*
* @param <T> the type of the input to the operation
*
* @since 1.8
*/
@FunctionalInterface
public interface Consumer<T> { /**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t); /**
* Returns a composed {@code Consumer} that performs, in sequence, this
* operation followed by the {@code after} operation. If performing either
* operation throws an exception, it is relayed to the caller of the
* composed operation. If performing this operation throws an exception,
* the {@code after} operation will not be performed.
*
* @param after the operation to perform after this operation
* @return a composed {@code Consumer} that performs in sequence this
* operation followed by the {@code after} operation
* @throws NullPointerException if {@code after} is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}

Predicate.java

/**
* Represents a predicate (boolean-valued function) of one argument.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #test(Object)}.
*
* @param <T> the type of the input to the predicate
*
* @since 1.8
*/
@FunctionalInterface
public interface Predicate<T> { /**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t); /**
* Returns a composed predicate that represents a short-circuiting logical
* AND of this predicate and another. When evaluating the composed
* predicate, if this predicate is {@code false}, then the {@code other}
* predicate is not evaluated.
*
* <p>Any exceptions thrown during evaluation of either predicate are relayed
* to the caller; if evaluation of this predicate throws an exception, the
* {@code other} predicate will not be evaluated.
*
* @param other a predicate that will be logically-ANDed with this
* predicate
* @return a composed predicate that represents the short-circuiting logical
* AND of this predicate and the {@code other} predicate
* @throws NullPointerException if other is null
*/
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
} /**
* Returns a predicate that represents the logical negation of this
* predicate.
*
* @return a predicate that represents the logical negation of this
* predicate
*/
default Predicate<T> negate() {
return (t) -> !test(t);
} /**
* Returns a composed predicate that represents a short-circuiting logical
* OR of this predicate and another. When evaluating the composed
* predicate, if this predicate is {@code true}, then the {@code other}
* predicate is not evaluated.
*
* <p>Any exceptions thrown during evaluation of either predicate are relayed
* to the caller; if evaluation of this predicate throws an exception, the
* {@code other} predicate will not be evaluated.
*
* @param other a predicate that will be logically-ORed with this
* predicate
* @return a composed predicate that represents the short-circuiting logical
* OR of this predicate and the {@code other} predicate
* @throws NullPointerException if other is null
*/
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
} /**
* Returns a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}.
*
* @param <T> the type of arguments to the predicate
* @param targetRef the object reference with which to compare for equality,
* which may be {@code null}
* @return a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
} /**
* Returns a predicate that is the negation of the supplied predicate.
* This is accomplished by returning result of the calling
* {@code target.negate()}.
*
* @param <T> the type of arguments to the specified predicate
* @param target predicate to negate
*
* @return a predicate that negates the results of the supplied
* predicate
*
* @throws NullPointerException if target is null
*
* @since 11
*/
@SuppressWarnings("unchecked")
static <T> Predicate<T> not(Predicate<? super T> target) {
Objects.requireNonNull(target);
return (Predicate<T>)target.negate();
}
}

Supplier.java

/**
* Represents a supplier of results.
*
* <p>There is no requirement that a new or distinct result be returned each
* time the supplier is invoked.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #get()}.
*
* @param <T> the type of results supplied by this supplier
*
* @since 1.8
*/
@FunctionalInterface
public interface Supplier<T> { /**
* Gets a result.
*
* @return a result
*/
T get();
}

Java之函数式接口@FunctionalInterface详解(附源码)的更多相关文章

  1. struts2内置拦截器和自定义拦截器详解(附源码)

    一.Struts2内置拦截器 Struts2中内置类许多的拦截器,它们提供了许多Struts2的核心功能和可选的高级特 性.这些内置的拦截器在struts-default.xml中配置.只有配置了拦截 ...

  2. 转载—— android 瀑布流的实现详解,附源码

    介绍 参考自:https://github.com/dodola/android_waterfall,因为原来的代码封装不好,所以,我根据源码的思路,重新写了一遍,所以有了现在这个项目:https:/ ...

  3. C# Socket-TCP异步编程原理详解附源码

    目录 目录异步原理主要方法源码Server源码:Client源码实验效果(广播为例)参考博客 TOC 异步原理 套接字编程原理:延续文件作用思想,打开-读写-关闭的模式. C/S编程模式如下: Ø 服 ...

  4. Java SPI机制实战详解及源码分析

    背景介绍 提起SPI机制,可能很多人不太熟悉,它是由JDK直接提供的,全称为:Service Provider Interface.而在平时的使用过程中也很少遇到,但如果你阅读一些框架的源码时,会发现 ...

  5. Android应用AsyncTask处理机制详解及源码分析

    1 背景 Android异步处理机制一直都是Android的一个核心,也是应用工程师面试的一个知识点.前面我们分析了Handler异步机制原理(不了解的可以阅读我的<Android异步消息处理机 ...

  6. Spring Boot启动命令参数详解及源码分析

    使用过Spring Boot,我们都知道通过java -jar可以快速启动Spring Boot项目.同时,也可以通过在执行jar -jar时传递参数来进行配置.本文带大家系统的了解一下Spring ...

  7. 【转载】Android应用AsyncTask处理机制详解及源码分析

    [工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果] 1 背景 Android异步处理机制一直都是Android的一个核心,也是应用工程师面试的一个 ...

  8. 详解ConCurrentHashMap源码(jdk1.8)

    ConCurrentHashMap是一个支持高并发集合,常用的集合之一,在jdk1.8中ConCurrentHashMap的结构和操作和HashMap都很类似: 数据结构基于数组+链表/红黑树. ge ...

  9. 线程池底层原理详解与源码分析(补充部分---ScheduledThreadPoolExecutor类分析)

    [1]前言 本篇幅是对 线程池底层原理详解与源码分析  的补充,默认你已经看完了上一篇对ThreadPoolExecutor类有了足够的了解. [2]ScheduledThreadPoolExecut ...

随机推荐

  1. Scala的正则表达式

    想使用scala的正则表达式,需要首先导入 import scala.util.matching.Regex 然后就可以使用了,实例如下: val pattern = new Regex(" ...

  2. callback、promise和async、await的使用方法

    callback 回调是一个函数被作为一个参数传递到另一个函数里,在那个函数执行完后再执行.通俗的讲就是 B函数被作为参数传递到A函数里,在A函数执行完后再执行B. promise Promise 是 ...

  3. IDEA 连接Docker 并部署

    安装docker 之前先更新系统: yum update 安装docker: yum install docker 启动docker: systemctl start docker docker 远程 ...

  4. 「UVA1185」Big Number 解题报告

    UVA1185 Big Number In many applications very large integers numbers are required. Some of these appl ...

  5. 1059 C语言竞赛 (20 分)C语言

    C 语言竞赛是浙江大学计算机学院主持的一个欢乐的竞赛.既然竞赛主旨是为了好玩,颁奖规则也就制定得很滑稽: 0.冠军将赢得一份"神秘大奖"(比如很巨大的一本学生研究论文集--). 1 ...

  6. Spring中常见的设计模式——代理模式

    一.代理模式的应用场景 生活中的中介,黄牛,等一系列帮助甲方做事的行为,都是代理模式的体现.代理模式(Proxy Pattern)是指为题对象提供一种代理,以控制对这个对象的访问.代理对象在客户端和目 ...

  7. ElementUi 表格取消全选框,用文字表示

    Echarts ElementUi 表格取消全选框,用文字表示 1.先看看实现的图 一. 添加添加复选框列 <el-table v-loading="zongShipLoading&q ...

  8. Linux下Qt+CUDA调试并运行

    Qt与CUDA相结合具体的操作主要修改qt项目中的配置文件pro.下面以测试的项目为例. 因为这是一个测试案例,代码很简单,下面将这几个文件的代码贴出来,方面后面对应pro文件和Makefile文件中 ...

  9. OBS Studio 完全开源免费录屏软件

    OBS是Open Broadcaster Software的简称,它是一款永久免费的直播软件.OBS直播软件相比XSplit,占用资源相对较少,对配置要求相对要低一点,相同点就是录制格式MP4,不用再 ...

  10. 天梯 L2 树的遍历(已知后序中序求层序)

    树的遍历 (25 分) 给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列.这里假设键值都是互不相等的正整数. 输入格式: 输入第一行给出一个正整数N(≤30),是二叉树中结点的个数.第二行 ...