一、Lambda表达式需要“函数式接口”的支持
Lambda 的设计者们为了让现有的功能与 Lambda 表达式良好兼容,考虑了很多方法,于是产生了函数接口这个概念。
函数接口指的是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,这样的接口可以隐式转换为 Lambda 表达式。
但是在实践中,函数式接口非常脆弱,只要某个开发者在该接口中添加一个函数,则该接口就不再是函数式接口进而导致编译失败。为了克服这种代码层面的脆弱性,并显式说明某个接口是函数式接口,Java 8 提供了一个特殊的注解@FunctionalInterface
,举个简单的函数式接口的定义:
@FunctionalInterface
public interface GreetingService {
void sayMessage(String message);
}
Java7 只能通过匿名内部类进行编程,例如:
GreetingService greetService = new GreetingService() {
@Override
public void sayMessage(String message) {
System.out.println("Hello " + message);
}
};
greetService.sayMessage("world");
Java8 可以采用 Lambda 表达方进行编程,例如:
GreetingService greetService = message -> System.out.println("Hello " + message);
greetService.sayMessage("world");
目前 Java 库中的所有相关接口都已经带有这个注解了,实践上java.lang.Runnable
和java.util.concurrent.Callable
是函数式接口的最佳例子!
- 函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。
可以使用注解
@FunctionalInterface
添加在该接口类上进行修饰,可以检查是否是函数式接口A.定义函数式接口
```java /**
- Fun
- encoding:UTF-8 *
@author Fcant 下午 14:51:50 2020/2/19/0019 */ @FunctionalInterface public interface Fun
{ Integer getValue(T t);
}
<a name="2hMiL"></a>
### B.函数式接口的使用
```java
// 函数式接口使用
@Test
public void funTest() {
Integer op = op(1000, (x) -> x * x);
System.out.println(op);
}
public Integer op(Integer in, Fun<Integer> fun) {
return fun.getValue(in);
}
二、Java四大内置核心函数式接口
函数式接口 | 参数类型 | 返回值类型 | 包含的方法 | 用途 |
---|---|---|---|---|
Consumer<T> 消费型接口 |
T |
void |
void accept(T t); |
对类型为T 的对象应用操作 |
Supplier<T> 供给型接口 |
无 | T |
T get(); |
返回类型为T 的对象 |
Function<T, R> 函数型接口 |
T |
R |
R apply(T t); |
对类型为T 的对象应用操作,并返回R类型的结果 |
Predicte<T> 断定型接口 |
T |
boolean |
boolean test(T t); |
确定类型为T 的对象是否满足某约束,并返回boolean 值 |
1、四大核心内置接口
A.Consumer
:消费型接口
void accept(T t);
// 1.Consumer<T> :消费型接口
public void happyTest(double money, Consumer<Double> consumer) {
consumer.accept(money);
}
@Test
public void consumerTest() {
happyTest(1000d, (x) -> System.out.println("本次消费:" + x + "元"));
}
B.Supplier
:供给型接口
T get();
// 2.Supplier<T> :供给型接口
public List<Integer> getNumList(int n, Supplier<Integer> supplier) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
Integer num = supplier.get();
list.add(num);
}
return list;
}
@Test
public void supplierTest() {
getNumList(10, () -> (int)(Math.random() * 100)).forEach(System.out::println);
}
C.Function<T, R>
:函数型接口
R apply(T t);
// 3.Function<T, R> :函数型接口
public String strHandler(String s, Function<String, String> function) {
return function.apply(s);
}
@Test
public void strTest() {
System.out.println(strHandler("gh", (s) -> s.toUpperCase()));
}
D.Predicate
:断言型接口
boolean test(T t);
// 4.Predicate<T> :断言型接口
public List<String> filterStr(List<String> list, Predicate<String> predicate) {
List<String> strings = new ArrayList<>();
for (String s : list) {
if (predicate.test(s)) {
strings.add(s);
}
}
return strings;
}
@Test
public void strFilterTest() {
List<String> stringList = Arrays.asList("Hello", "Fcant", "Lambda", "ww", "ok");
filterStr(stringList, (s) -> s.length() > 3).forEach(System.out::println);
}
2、其他接口
函数式接口 | 参数类型 | 返回值类型 | 包含的方法 | 用途 |
---|---|---|---|---|
BiFunction<T, U, R> |
T,U | R | R apply(T t, U u); |
对类型为T的对象应用操作 |
UnaryOperator<T> (Function子接口) |
T | T | T apply(T t); |
返回类型为T的对象 |
BinaryOperator<T> (BiFunction子接口) |
T, T | T | T apply(T t1, T t2); |
对类型为T的对象应用操作,并返回R类型的结果 |
BiConsumer<T, U> |
T, U | void | void accept(T t, U u); |
确定类型为T的对象是否满足某约束,并返回boolean值 |
ToIntFunction<T> ToLongFunction<T> ToDoubleFunction<T> |
T | int long double |
分别计算int,long,double、值的函数 | |
IntFunction<R> LongFunction<R> DoubleFunction<R> |
int long double |
R | 参数分别为int,long,double类型的函数 |