Java函数式接口使用
从Function的四个接口来理解函数式思想
Function定义与使用
需要知道,Function接口只是一个接口,所有满足此接口apply方法签名的,都可以使用此接口。
如果将方法的参数定义为Function类型,则可以以方法引用的形式,将满足Function接口apply方法定义的方法作为参数传递到此方法中。
示例:
public static void de() {
func(Demo::convert);
}
public static void func(Function<Integer, String> func) {
String apply = func.apply(0);
System.out.println(apply);
}
public static String convert(Integer num) {
return num + "";
}
func方法接受一个参数,参数的类型为Function,并且指定了泛型。而convert方法,接收一个integer类型的参数,返回一个string类型的参数,方法定义满足func方法中指定泛型的Function接口的apply方法定义。所以,func方法可以接收convert方法作为其参数。
如果使用lamda表达式替代方法引用,如下:
public static void de() {
func((a) -> a + "");
}
public static void func(Function<Integer, String> func) {
String apply = func.apply(0);
System.out.println(apply);
}
public static String convert(Integer num) {
return num + "";
}
可以看到,在func方法中 func.apply(0) ,入参是写死的,Function::apply方法需要一个参数,但是func方法只有一个Function参数,在func方法里使用Function类型的参数时,手动指定了0作为入参。
理解这两点,再看看Map的foreach遍历:
default void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}
Map::forEach方法,接收一个BiConsumer类型的参数,而BiConsumer接口的抽象方法accept,接收两个参数,没有返回值。于是,我们可以像下面这样便捷的使用Map::forEach方法:
public static void de() {
Map<Integer, String> map = new HashMap<>();
map.forEach((k, v) -> {
String s = k + v + "";
});
}
lambda表达式有两个入参k,v没有返回值。
使用方法引用也是完全可以的:
public static void de() {
Map<Integer, String> map = new HashMap<>();
map.forEach(Demo::mapEach);
}
public static void mapEach(Integer k, String v) {
return;
}
相信看到这里,已经能够理解怎么使用function接口以及方法引用与lambda表达式的等价替换了。