参考:
https://www.jianshu.com/p/63771441ba31
https://blog.csdn.net/qq_28410283/article/details/80704487
https://www.yiibai.com/geek/detail/518
1、Consumer
源码:
package java.util.function;
import java.util.Objects;
/**
* 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.
*
* 表示“接受一个参数输入且没有任何返回值的操作“。不同于其它的函数式接口,Consumer期望通过方法的实现来执行具体的操作。
*
* <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.
*
* 默认方法,提供链式调用方式执行。执行流程:先执行本身的accept在执行传入参数after.accept方法。
* 该方法会抛出NullPointerException异常。
* 如果在执行调用链时出现异常,会将异常传递给调用链功能的调用者,且发生异常后的after将不会在调用。
*
* @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); };
}
}
使用实例:
package jdk8;
import java.util.function.Consumer;
public class ConsumerTest {
public static void main(String[] args) {
testConsumer();
testAndThen();
}
/**
* 一个简单的平方计算
*/
public static void testConsumer(){
Consumer<Integer> square = x -> System.out.println("print square : " + x * x);
square.accept(2);
}
/**
* 定义3个Consumer并按顺序进行调用andThen方法,其中consumer2抛出NullPointerException。
*/
public static void testAndThen(){
Consumer<Integer> consumer1 = x -> System.out.println("first x : " + x);
Consumer<Integer> consumer2 = x -> {
System.out.println("second x : " + x);
throw new NullPointerException("throw exception test");
};
Consumer<Integer> consumer3 = x -> System.out.println("third x : " + x);
consumer1.andThen(consumer2).andThen(consumer3).accept(1);
}
}
执行结果:
print square : 4
first x : 1
second x : 1
Exception in thread "main" java.lang.NullPointerException: throw exception test
at jdk8.ConsumerTest.lambda$testAndThen$2(ConsumerTest.java:27)
at java.util.function.Consumer.lambda$andThen$0(Consumer.java:65)
at java.util.function.Consumer.lambda$andThen$0(Consumer.java:65)
at jdk8.ConsumerTest.testAndThen(ConsumerTest.java:31)
at jdk8.ConsumerTest.main(ConsumerTest.java:9)
Process finished with exit code 1
结论:
- 默认方法,提供链式调用方式执行。执行流程:
先执行本身的accept
,再执行传入参数after.accept方法
。 - 依次执行andThen的Consumer的accept,直到遇到null异常,不再执行异常后的andThen。
jdk内对Consumer的典型使用:
在jdk内对Consumer的典型使用非foreach莫属了(在 java.lang.Iterable内),下面是源码:
/**
* Performs the given action for each element of the {@code Iterable}
* until all elements have been processed or the action throws an
* exception. Unless otherwise specified by the implementing class,
* actions are performed in the order of iteration (if an iteration order
* is specified). Exceptions thrown by the action are relayed to the
* caller.
*
* @implSpec
* <p>The default implementation behaves as if:
* <pre>{@code
* for (T t : this)
* action.accept(t);
* }</pre>
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
* @since 1.8
*/
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
2、BiConsumer
源码:
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u);
/**本接口中的accept先执行,传入的BiConsumer 接口类型的参数,后执行accept*/
default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> after) {
Objects.requireNonNull(after);
return (l, r) -> {
accept(l, r);
after.accept(l, r);
};
}
}
使用实例:
跟Consumer一样,都有一个 accept方法
,只不过,Consumer接受1个泛型参数
,而BiConsumer接受2个泛型参数
。
Map<String, String> map = new HashMap<>();
map.put("a", "a");
map.put("b", "b");
map.put("c", "c");
map.put("d", "d");
map.forEach((k, v) -> {
System.out.println(k);
System.out.println(v);
});
Map接口的终端操作,forEach的参数就是BiConsumer函数接口
,对HashMap 的数据进行消费;BiConsumer函数接口还有一个默认函数,andThen
,接收一个BiConsumer接口
,先执行本接口的
,再执行传入的参数
。
package com.yiibai.tutorial.lambda;
import java.util.function.BiConsumer;
public class BiConsumerExample2 {
public static void main(String[] args) {
BiConsumer addition = (a b) -> {
System.out.println(a + b);
};
BiConsumer subtraction = (a b) -> {
System.out.println(a - b);
};
// Using andThen()
addition.andThen(subtraction).accept(10 6);
}
}
执行结果:
16
4