上一篇博文java8函数式编程--收集器collector:(http://my.oschina.net/joshuashaw/blog/487322)讲得比较随性,并没有把源码一句一句拿出来分析,后来发现groupingBy方法最后有一个if-else分支用来返回不同类型的collector,一个是不需要特定finisher的,另一个需要使用下游收集器的finisher,今天细看源码,发现了几句神奇的代码,拿出来讲一讲。
先贴源码:
public static <T, K, D, A, M extends Map<K, D>>
Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
Supplier<M> mapFactory,
Collector<? super T, A, D> downstream) {
Supplier<A> downstreamSupplier = downstream.supplier();
BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
downstreamAccumulator.accept(container, t);
};
BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner());
@SuppressWarnings("unchecked")
Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory;
if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);
}
else {
/*---------------------------
---- --神奇的代码-- ------
-----------------------------
@SuppressWarnings("unchecked")
Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
Function<Map<K, A>, M> finisher = intermediate -> {
intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
@SuppressWarnings("unchecked")
M castResult = (M) intermediate;
return castResult;
};
-----------------------------
----- ---神奇的代码----- ----
--------------------------*/
return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
}
}
抽出来强调一下
@SuppressWarnings("unchecked")
Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
Function<Map<K, A>, M> finisher = intermediate -> {
intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
@SuppressWarnings("unchecked")
M castResult = (M) intermediate;
return castResult;
};
这里我们看到,类型为
(Function<A, D>) downstream.finisher()
被强制类型转换成
(Function<A, A>) downstreamFinisher
然后是
Map<K,A> intermediate
被强制类型转换成
Map<K,D> intermediate
我想,这都行?于是我写了两条语句
Fuction<String,Integer> f1 = Integer::parse; Fuction<String,String> f2 = (Fuction<String,String>) f1;
编译器报错。
但是为什么groupingBy方法里面可以这样写?于是我按照groupingBy方法写了一个测试类,代码如下:
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
public class InterestingTest<K,T,V> {
private Map<K,T> Tmap = null;
private Map<K,V> Vmap = null;
private Function<T,V> Vf = null;
private Function<T,T> Tf = null;
public InterestingTest(Map<K,T> m,Function<T,V> f){
Tmap = m;
Vf = f;
Tf = (Function<T, T>) f;
Tmap.replaceAll((k,t)->Tf.apply(t));
Vmap = (Map<K, V>) Tmap;
}
public Map<K, V> getMap(){
return Vmap;
}
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("1", 1);
map.put("2", 2);
map.put("3", 3);
map.put("4", 4);
Map<String,String> newMap =
new InterestingTest<String,Integer,String>(map,Integer::toBinaryString)
.getMap();
newMap.entrySet().stream()
.forEach(e->{System.out.println(e.getKey()+" "+e.getValue());});
}
}
代码只是报警告,一运行下来一点问题都没有,完美得出结果。
几天前刷知乎看到java实现不了真正的泛型,现在算是明白了。
其实,对于java泛型的实现,只是编译器在编译阶段帮助你进行类型转型,像Map<String,Integer>类型,实际是保存你的对象的地址,对于Map来说,他只是存了Integer的地址,将Integer视为终极父类Object的子类,当你调用get(key)的时候,最后返回Object类型给你之前帮你强制类型转换成了Integer,就像:
put(key,IntegerObject){
this.object = IntegerObject;
}
get(key){
return (Integer) findCorrentObject;
}
所以从泛型的角度看,代码没有错误,但是会警告你这代码可能导致类型转换而出现的错误,于是我们可以看到
@SuppressWarnings("unchecked")
来去除警告。
但是,当你使用的是具体的类型时,编译器有职责给你报错,他认为你写的这行代码很有可能发生错误。
总结:都是兼容和初始开发人员省事而留下的问题啊。
原文:http://my.oschina.net/joshuashaw/blog/487766