[英]Getting a ClassCastException when using a custom Collector with java 8 streams
我有一個自定義的Collector
public class ClusteringCollector extends java.util.stream.Collector<MyModel, Map<String, ClusterModel>, SortedSet<Map.Entry<Integer, ClusterModel>>> {
@Override
public Supplier<Map<String, MyOtherModel>> supplier() {
return HashMap::new;
}
@Override
public BiConsumer<Map<String, ClusterModel>, MyModel> accumulator() {
return (l, r) -> {
String mapKey = r.getURI();
if(l.containsKey(mapKey)) {
l.get(mapKey).addCluster(r.getCluster());
} else {
l.put(mapKey, r.getCluster());
}
}
}
@Override
public BinaryOperator<Map<String, ClusterModel>> combiner() {
return (left, right) -> {
for(Map.Entry<String, ClusterModel> e : right.entrySet()) {
e.getValue().setClusterCount(1);
if(left.containsKey(e.getKey())) {
left.get(e.getKey()).merge(e.getValue());
} else {
left.put(e.getKey(), e.getValue());
}
}
return left;
};
}
@Override
public Function<Map<String, ClusterModel>, SortedSet<Map.Entry<Integer, ClusterModel>>> finisher() {
return (accumulated) -> {
SortedSet<Map.Entry<Integer, ClusterModel>> finished = new TreeSet<>((mine, theirs) -> {
Double t1 = mine.getValue().getClusterCount() * mine.getValue().getClusterWeight();
Double t2 = theirs.getValue().getClusterCount() * theirs.getValue().getClusterWeight();
return t2.compareTo(t1);
});
Map<Integer, ClusterModel> tempMap = new LinkedHashMap<>();
for(Map.Entry<String, ClusterModel> e : accumulated.entrySet()) {
if(tempMap.containsKey(e.getValue().hashCode())) {
tempMap.get(e.getValue().hashCode()).merge(e.getValue());
} else {
tempMap.put(e.getValue().hashCode(), e.getValue());
}
}
finished.addAll(tempMap.entrySet());
return finished;
};
}
@Override
public Set<Characteristics> characteristics() {
return EnumSet.of(Characteristics.UNORDERED, Characteristics.IDENTITY_FINISH);
}
}
我通過以下方式使用收集器
try (Stream<MyModel> resultStream = generateDataStream()) {
SortedSet<Map.Entry<Integer, ClusterModel>> clusters = resultStream.collect(new ClusteringCollector()); // This line throws a ClassCastException
}
問題是,當我嘗試運行上面的collect
方法時,我一直收到ClassCastException
。 這是堆棧跟蹤
java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.SortedSet
com.mycomp.abc.core.services.DefaultClusteringServiceImpl.findClusters(DefaultClusteringServiceImpl.java:78)
com.mycomp.abc.core.webservices.ClusteringWebService.getClustersFromQuery(ClusteringWebService.java:67)
com.mycomp.abc.core.webservices.ClusteringWebService$Proxy$_$$_WeldClientProxy.getClustersFromQuery(Unknown Source)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:137)
org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:296)
org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:250)
org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:237)
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:356)
org.jboss.resteasy.core.SynchronousDispatcher.invokePropagateNotFound(SynchronousDispatcher.java:217)
org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:224)
org.jboss.resteasy.plugins.server.servlet.FilterDispatcher.doFilter(FilterDispatcher.java:62)
有人可以告訴我為什么會這樣嗎? 我沒有收到任何編譯錯誤,並且finisher
將Map
正確轉換為SortedSet
。
發布的代碼中存在多個錯誤,表明這不是實際的代碼,但是主要問題是可以識別的。 盡管在裝訂器中進行了復雜的轉換,但您仍指定了IDENTITY_FINISH
特性。
IDENTITY_FINISH
特性暗示整理器就像Function.identity()
,但是在運行時,Stream實現無法檢查泛型簽名是否與該聲明兼容。 當它使用此特性決定跳過裝訂器時,它將僅返回容器對象,在您的情況下是HashMap
,當然,該對象不能分配給SortedSet
。
最后,這是此錯誤的更好結果。 更糟糕的是,如果容器和結果類型兼容,並且起初沒有忽略不重要的修整器的跳過。 因此,在指定IDENTITY_FINISH
特征時要小心。
請注意,當您不實現Collector
,而是通過將函數傳遞給Collector.of(…)
來構造一個,則無需指定該特征,因為將根據您是否指定了finisher函數來注入該特征。 對於沒有整理程序的重載方法,泛型簽名甚至可以確保容器類型與結果類型匹配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.