常用函数式接口的解读及使用
前言版本Supplierdemo
Consumerdemo
Predicatedemo
Functiondemo
UnaryOperatordemo
BinaryOperatordemo
总结
前言
Java8 以来推出的 lambda 表达式使得程序员的代码越来越 优雅,配合 函数式接口 一起使用,很多繁杂的代码可以变得十分的 轻巧 。官方也在 java.util.function 下为我们提供了很多 函数式接口,本章节做个简单地梳理
版本
JDK11
Supplier
@FunctionalInterface
public interface Supplier<T> {
T
get();
}
不需要参数,但返回一个结果,不吃光吐,生产者
针对不同类型的结果,还提供了 IntSupplier DoubleSupplier 等类
demo
public class SupplierTest {
@Test
public void test1() {
s(() -> "hello");
is(() -> 1);
}
private void s(Supplier supplier
) {
System
.out
.println(supplier
.get());
}
private void is(IntSupplier intSupplier
) {
System
.out
.println(intSupplier
.getAsInt() * 2);
}
}
Consumer
@FunctionalInterface
public interface Consumer<T> {
void accept(T t
);
default Consumer
<T> andThen(Consumer
<? super T
> after
) {
Objects
.requireNonNull(after
);
return (T t
) -> { accept(t
); after
.accept(t
); };
}
}
接受一个参数,但没有返回值,只吃不吐,消费者
提供了 andThen 方法,允许后缀一个 Consumer 再消费一次
BiConsumer 接受两个参数
同样地,也提供了其他类型参数的 Consumer 比如 DoubleConsumer ObjDoubleConsumer 等
demo
public class ConsumerTest {
@Test
public void test1() {
c(1, System
.out
::println
);
bc(1, 2, (i
, j
) -> System
.out
.print(
Integer
.parseInt(i
.toString()) + Integer
.parseInt(j
.toString()) + " = "));
}
private void c(int i
, Consumer consumer
) {
consumer
.andThen(j
-> System
.out
.println(" = " + j
)).accept(i
);
}
private void bc(int i
, int j
, BiConsumer biConsumer
) {
biConsumer
.andThen((x
, y
) -> System
.out
.println(x
+" + "+ y
)).accept(i
, j
);
}
}
结果:
1 = 1
3 = 1 + 2
Predicate
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t
);
default Predicate
<T> and(Predicate
<? super T
> other
) {
Objects
.requireNonNull(other
);
return (t
) -> test(t
) && other
.test(t
);
}
default Predicate
<T> negate() {
return (t
) -> !test(t
);
}
default Predicate
<T> or(Predicate
<? super T
> other
) {
Objects
.requireNonNull(other
);
return (t
) -> test(t
) || other
.test(t
);
}
static <T> Predicate
<T> isEqual(Object targetRef
) {
return (null
== targetRef
)
? Objects
::isNull
: object
-> targetRef
.equals(object
);
}
@SuppressWarnings("unchecked")
static <T> Predicate
<T> not(Predicate
<? super T
> target
) {
Objects
.requireNonNull(target
);
return (Predicate
<T>)target
.negate();
}
}
接受一个参数,返回一个 boolean 值
提供了三个默认方法 and negate or,方法名 和 方法的实现语义 都特别清晰,及对应了 &&(与) !(非) ||(或) 逻辑运算
还提供了两个静态方法 isEqual 返回一个语义为 是否与 targetRef 相等的 Predicate not 其实相当于 target.negate()
BiPredicate 接受两个参数,且不提供上述两个静态方法
同样地,也提供了针对其他类型参数的 IntPredicate DoublePredicate 等等
demo
public class PredicateTest {
@Test
public void test1() {
p(1, i
-> Integer
.parseInt(i
.toString()) > 0, i
-> Integer
.parseInt(i
.toString()) < 0);
System
.out
.println("===========================================");
System
.out
.println(Predicate
.not(Predicate
.isEqual("0")).test("1"));
}
private void p(int i
, Predicate p1
, Predicate p2
) {
System
.out
.println(p1
.test(i
));
System
.out
.println(p2
.test(i
));
System
.out
.println(p1
.and(p2
).test(i
));
System
.out
.println(p1
.or(p2
).test(i
));
System
.out
.println(p1
.negate().test(i
));
}
}
Function
@FunctionalInterface
public interface Function<T, R> {
R
apply(T t
);
default <V> Function
<V, R> compose(Function
<? super V
, ? extends T> before
) {
Objects
.requireNonNull(before
);
return (V v
) -> apply(before
.apply(v
));
}
default <V> Function
<T, V> andThen(Function
<? super R
, ? extends V> after
) {
Objects
.requireNonNull(after
);
return (T t
) -> after
.apply(apply(t
));
}
static <T> Function
<T, T> identity() {
return t
-> t
;
}
}
接受一个参数,返回一个参数
提供了 compose 方法在当前 Function 之前执行,返回值用于当前 Function 。andThen 方法在当前 Function 之后执行,以当前 Function 的返回值为参数
提供了一个静态方法 identity ,返回一个啥也不干的 Function
BiFunction 接受两个参数,返回一个参数,只提供了默认方法 andThen
同样的,针对其他类型参数提供了 DoubleFunction DoubleToIntFunction 等
demo
public class FunctionTest {
@Test
public void test1() {
f(1
, i
-> Integer
.parseInt(i
.toString()) - 1
, i
-> Integer
.parseInt(i
.toString()) * 2);
}
public void f(int i
, Function f1
, Function f2
) {
System
.out
.println(f1
.compose(f2
).apply(i
));
System
.out
.println(f1
.andThen(f2
).apply(i
));
}
}
结果:
1
0
UnaryOperator
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
static <T> UnaryOperator
<T> identity() {
return t
-> t
;
}
}
Function 的子类,即入参和结果类型一致的 Function ,提供了静态方法 identity 获取 UnaryOperator 实例
同样的,针对不同类型的参数还有 DoubleUnaryOperator IntUnaryOperator 等
demo
public class UnaryOperatorTest {
@Test
public void test1() {
u(1, UnaryOperator
.identity());
}
public void u(int i
, UnaryOperator unaryOperator
) {
System
.out
.println(unaryOperator
.apply(i
));
}
}
BinaryOperator
@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
public static <T> BinaryOperator
<T> minBy(Comparator
<? super T
> comparator
) {
Objects
.requireNonNull(comparator
);
return (a
, b
) -> comparator
.compare(a
, b
) <= 0 ? a
: b
;
}
public static <T> BinaryOperator
<T> maxBy(Comparator
<? super T
> comparator
) {
Objects
.requireNonNull(comparator
);
return (a
, b
) -> comparator
.compare(a
, b
) >= 0 ? a
: b
;
}
}
BiFunction 的子类,即两个入参和返回值的类型都一致的 BiFunction
提供了两个静态方法,minBy 根据传入的 Comparator 方法入参里的较小值, maxBy 相反
针对不同类型的参数,提供了 IntBinaryOperator DoubleBinaryOperator 等类
demo
public class BinaryOperatorTest {
@Test
public void bo() {
System
.out
.println(BinaryOperator
.maxBy((a
, b
) -> ((User
) a
).id
- ((User
) b
).id
)
.apply(new User(1), new User(2)));
System
.out
.println(BinaryOperator
.minBy((a
, b
) -> ((User
) a
).id
- ((User
) b
).id
)
.apply(new User(1), new User(2)));
}
class User {
int id
;
public User(int id
) {
this.id
= id
;
}
@Override
public String
toString() {
return "User{" +
"id='" + id
+ '\'' +
'}';
}
}
}
结果:
User
{id
='2'}
User
{id
='1'}
总结
以上 函数式接口 基本涵盖了日常开发能用到的所有场景,使用起来及其舒适