我有一个curl_setopt($cHandler, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($cHandler, CURLOPT_SSL_VERIFYPEER, false);
,我想提供这些地图的输入集合的视图,即Iterable<Map<? extends K, ? extends V>>
。
我可以像这样构造一个新的Set<Map.Entry<K, V>>
(演员触发未经检查的警告,但编译):
Set
但是,这需要复制集,并且不会与支持映射保持同步。我尝试过这样的事情:
ImmutableSet.Builder<Map.Entry<K, V>> builder = ImmutableSet.builder();
for(Map<? extends K, ? extends V> map : chain) {
for(Map.Entry<? extends K, ? extends V> e : map.entrySet()) {
builder.add((Map.Entry<K, V>) e);
}
}
return builder.build();
但这无法编译,错误:
Set<Map.Entry<K, V>> unionSet = ImmutableSet.of(); for(Map<? extends K, ? extends V> map : chain) { unionSet = Sets.union((Set<Map.Entry<K, V>>)map.entrySet(), unionSet); } return unionSet;
我期待一个类似的不安全的演员,但在这种情况下似乎是禁止的,大概是由于嵌套的泛型。
所以有两个问题:
Cannot cast from Set<Map.Entry<capture#27-of ? extends K,
capture#28-of ? extends V>> to Set<Map.Entry<K,V>>
)?答案 0 :(得分:0)
这在技术上可以使用不安全的原始投射
Set<Map.Entry<K, V>> unionSet = ImmutableSet.of();
for(Map<? extends K, ? extends V> map : chain) {
unionSet = Sets.union((Set) map.entrySet(), unionSet);
}
......这几乎可以肯定是提供入口集联合的实时视图的最佳方式。
至于为什么不允许通用论证的演员,我怀疑Set<Map.Entry<? extends K, ? extends V>>
和Set<Map.Entry<K, V>>
之间在技术上没有子类型关系。对于冗长但技术上不同的Set<? extends Map.Entry<? extends K, ? extends V>>
,它可能有所不同,这在技术上是Set<Map.Entry<K, V>>
的概括,而另一个则不是。{/ p>
答案 1 :(得分:0)
您可以通过执行双重转换而不使用原始类型来编译您的不安全转换,例如:
static <K, V> Set<Map.Entry<K, V>> unionSet(Iterable<Map<? extends K, ? extends V>> maps) {
Set<Map.Entry<K, V>> unionSet = ImmutableSet.of();
for (Map<? extends K, ? extends V> map : maps) {
@SuppressWarnings("unchecked") // unsafe! see below
Set<Map.Entry<K, V>> castEntrySet = (Set<Map.Entry<K, V>>) (Set<?>) map.entrySet();
unionSet = Sets.union(castEntrySet, unionSet);
}
return unionSet;
}
但是generic types aren't covariant for a reason。以下是一个不安全原因的例子:
Map<String, Integer> intMap = new HashMap<>();
intMap.put("key", 42);
Set<Map.Entry<String, Number>> unionSet = unionSet(ImmutableList.of(intMap));
Iterables.getOnlyElement(unionSet).setValue(0.42);
// java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
Integer shouldBeAnInt = intMap.get("key");