Java supports anonymous functions, named Lambda Expressions, starting with JDK 8.
Lambda Expressions, a new language feature, has been introduced in this release. They enable you to treat functionality as a method argument, or code as data. Lambda expressions let you express instances of single-method interfaces (referred to as functional interfaces) more compactly.
Java8开始支持匿名函数,又叫Lambda表达式。
Lambda表达式允许函数作为方法参数,并且可以让单方法接口(也叫函数式接口)的表达更为紧凑。
Lambda表达式Demo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// with no parameter
() -> System.out.println("Hello, world.")
// with one parameter (this example is an identity function).
a -> a
// with one expression
(a, b) -> a + b
// with explicit type information
(long id, String name) -> "id: " + id + ", name:" + name
// with a code block
(a, b) -> { return a + b; }
// with multiple statements in the lambda body. It needs a code block.
// This example also includes two nested lambda expressions (the first one is also a closure).
(id, defaultPrice) -> {
Optional<Product> product = productList.stream().filter(p -> p.getId() == id).findFirst();
return product.map(p -> p.getPrice()).orElse(defaultPrice);
}
函数式接口
A functional interface is any interface that contains only one abstract method.
函数式接口:任何只有一个抽象方法的接口。
函数式接口可以被隐式转换为 lambda 表达式。
定义一个函数式接口如下:
1
2
3
interface GreetingService {
void sayMessage(String message);
}
可以使用Lambda表达式来表示该接口的一个实现:
1
2
GreetingService greetService = message -> System.out.println("Hello " + message);
greetService.sayMessage("world!");
Java8使用Lambda时,需要声明函数式接口。因此,JDK设计人员内置了四大核心函数式接口。
1、消费型接口Consumer< T >
消费型接口:有参数,无返回值。
1
2
3
4
5
@Test
public void testConsumer() {
Consumer<Double> consumer = m -> System.out.format("买苹果花费:%.1f元\n", m);
consumer.accept(1.1);
}
2、供给型接口Supplier< T >
供给型接口:无参数,有返回值。
1
2
3
4
5
@Test
public void testSupplier() {
Supplier<Double> supplier = () -> Math.random() * 10;
System.out.format("卖苹果盈利:%.1f元\n", supplier.get());
}
3、函数型接口Function< T, R >
函数型接口:有参数,有返回值。
1
2
3
4
5
6
@Test
public void testFunction() {
Function<String, String> function = (s1) -> StringUtils.upperCase(s1);
String name = "Jeff";
System.out.format("名字:%s,大写是:%s", name, function.apply(name));
}
4、断言型接口Predicate< T >
断言型接口:有参数,返回值为布尔值。
1
2
3
4
5
6
7
8
9
10
@Test
public void testPredicate() {
Predicate<String> predicate = (s1) -> StringUtils.length(s1) >= 5;
List<String> names = Arrays.asList(new String[]{"Army", "Luna", "Elle", "Katherine"});
for (String name : names) {
if (predicate.test(name)) {
System.out.println(name);
}
}
}
5、四大核心函数式接口补充
四大核心函数式接口,除了核心的抽象方法外,还有几个有意思的默认、静态方法。
Predicate:增加了逻辑运算方法,这样就可以把很多断言型接口串起来。
1
2
3
4
5
6
7
8
9
10
# 与
default Predicate<T> and(Predicate<? super T> other);
# 非
default Predicate<T> negate();
# 或
default Predicate<T> or(Predicate<? super T> other);
# 根据equal方法,判断两个对象是否相等
static <T> Predicate<T> isEqual(Object targetRef);
# 非
static <T> Predicate<T> not(Predicate<? super T> target)
Consumer:增加了andThen方法,可以把多个消费型接口串起来。
1
default Consumer<T> andThen(Consumer<? super T> after)
Function:增加了前序、后续函数。
1
2
3
4
# V -> T, T -> R
default <V> Function<V, R> compose(Function<? super V, ? extends T> before);
# T -> R, R -> V
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after);