首先看Map interface中关于merge方法的代码:
default V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Objects.requireNonNull(value);
V oldValue = get(key);
V newValue = (oldValue == null) ? value :
remappingFunction.apply(oldValue, value);
if(newValue == null) {
remove(key);
} else {
put(key, newValue);
}
return newValue;
}
注:由于JDK8中为了实现行为参数化,以及老版本的兼容,为接口增加了默认方法实现,使用default来修饰,因此我们可以在接口中看到默认方法的实现。
上面代码段其实很好理解,可能平时自己也会大量写上述代码,只是没想到JDK8帮我们写好了,哈哈哈哈。
一起来看一下代码吧。首先这个方法要三个参数,第一个K key,就是Map的key,第二个V value,就是map的value,这两个很好理解,关键就是第三个BiFunction<? super V, ? super V, ? extends V> remappingFunction,这是个什么?
这就是行为参数化,什么是行为参数化?首先,行为在java里面就是被抽象为方法,然后就是参数化,意思是变成一个参数,那么行为参数化的字意就是将行为变成参数,也就是把方法当成一个参数,什么样的方法呢?
java里面最擅长的就是抽象,但是Java里面没有抛开类和接口,单独对方法进行引用,为了解决这个问题,Java8开始增加函数式接口,以此来解决这个问题。函数式接口就是只有一个抽象方法的接口,定义的时候使用@FunctionalInterface来修饰。函数式接口对方法的引用提供了解决方案。JDK中提供了大量的函数式接口供我们使用。
话归正题,我们来看看JDK8中关于BiFunction的代码吧。
public interface BiFunction<T, U, R> {
/**
* Applies this function to the given arguments.
*
* @param t the first function argument
* @param u the second function argument
* @return the function result
*/
R apply(T t, U u);
/**
* Returns a composed function that first applies this function to
* its input, and then applies the {@code after} function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of output of the {@code after} function, and of the
* composed function
* @param after the function to apply after this function is applied
* @return a composed function that first applies this function and then
* applies the {@code after} function
* @throws NullPointerException if after is null
*/
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t, U u) -> after.apply(apply(t, u));
}
BiFunction接口中的apply方法定义是,入参为两个对象:T、U,返回一个对象R。
回到merge方法的代码
V newValue = (oldValue == null) ? value :
remappingFunction.apply(oldValue, value);
Map的旧值为空,直接把新值放进去,如果不为空,再来一顿操作,返回一个操作后的值,最终得到Map当前key对应的新值。
代买的最后再来一次判断,看你这一顿操作后会不会又搞成一个null,如果不是空值就ok。
好了,这就是merge方法的相关源码。你学废了吗