Java 函数式接口

Java 8 函数式接口

函数接口概述

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口可以被隐式转换为 lambda 表达式。
Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。

函数接口定义

如定义了一个函数式接口如下:

1
2
3
4
5
@FunctionalInterface
interface GreetingService
{
void sayMessage(String message);
}

那么就可以使用Lambda表达式来表示该接口的一个实现(注:JAVA 8 之前一般是用匿名类实现的):

1
GreetingService greetService1 = message -> System.out.println("Hello " + message);

@FunctionalInterface注解

与@Override 注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface 。该注解可用于一个接口的定义上,一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。需要注意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。

lambda表达式

(参数列表)->{代码}

常用函数式接口

supplier生产数据函数式接口

Supplier 接口翻译过来就是提供者,目的是生产数据,该接口对应的方法类型为不接受参数,但是提供一个返回值,通俗的理解为这种接口是无私的奉献者,不仅不要参数,还返回一个值,使用get()方法获得这个返回值。

1
2
3
4
public static void main(String[] args) {
Supplier<String> getInstance = () -> "HelloWorld!";
System.out.println(getInstance.get());
}

Consumer消费函数式接口

该接口对应的方法类型为接收一个参数,没有返回值,可以通俗的理解成将这个参数’消费掉了’,一般来说使用Consumer接口往往伴随着一些期望状态的改变或者事件的发生,例如最典型的forEach就是使用的Consumer接口,虽然没有任何的返回值,但是却向控制台输出了语句。
Consumer 使用accept对参数执行行为。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
accept(T t)
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello ");
Consumer<StringBuilder> consumer = (str) -> str.append("Jack!");
consumer.accept(sb);
System.out.println(sb.toString()); // Hello Jack!
}

andThen(Consumer<? super T> after)
public static void main(String[] args) {
Consumer<StringBuilder> consumer1 = (str) -> str.append(" Bob!");
consumer.andThen(consumer1).accept(sb);
System.out.println(sb.toString()); // Hello Jack! Bob
}

Functio<T,R> 类型转换函数式接口

T—函数的输入类型,R-函数的输出类型,也就是通过这个函数,可以将一个类型转换为另一个类型,比如下面的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
apply(T t)
public static void main(String[] args) {
Function<String, String> function = a -> a + " Jack!";
System.out.println(function.apply("Hello")); // Hello Jack!
}

andThen(Function<? super R,? extends V> after)
public static void main(String[] args) {
Function<String, String> function = a -> a + " Jack!";
Function<String, String> function1 = a -> a + " Bob!";
String greet = function.andThen(function1).apply("Hello");
System.out.println(greet); // Hello Jack! Bob!
}

Predicate 断言函数式接口

predicate<T,Boolean> 断言接口,顾名思义,中文中的‘是’与‘不是’是中文语法的谓语,同样的该接口对应的方法为接收一个参数,返回一个Boolean类型值,多用于判断与过滤,当然你可以把他理解成特殊的Funcation<T,R>,但是为了便于区分语义,还是单独的划了一个接口,使用test()方法执行这段行为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   
public static void main(String[] args) {
Predicate<Integer> predicate = number -> number != 0;

test(T t) 等价于 ==
System.out.println(predicate.test(10)); //true

and(Predicate<? super T> other) 等价于 and
predicate = predicate.and(number -> number >= 10);
System.out.println(predicate.test(10)); //true

or(Predicate<? super T> other) 等价于 or
predicate = predicate.or(number -> number != 10);
System.out.println(predicate.test(10)); //true

negate() 等价于 !=
predicate = predicate.negate();
System.out.println(predicate.test(10)); //false

}