向下转发番石榴地图类

时间:2015-06-02 14:36:14

标签: java guava

我在使用guava数据类型

的系统中工作了大约一个月
ImmutableMap<String, Object>

即使我的开发人员喜欢它,事情也很有效。这很棒。直到昨天。我们有一个记录集,我们必须将它作为ImmutableListMultimap引入,我们必须将它转换为我们的ImmutableMap类型。

这是我们的编译错误

ImmutableListMultimap<String, Object> tst = new bla bla bla;
        ImmutableMap<String, Object> tst2 = (ImmutableMap<String, Object>) tst.asMap();

错误本身是

Cannot cast from ImmutableMap<String,Collection<Object>> to ImmutableMap<String,Object>

现在进行此演员表不是一个选择。必须要做,或者我们必须回去重新设计一个月的工作。不会发生。我现在解决这个问题的唯一选择是构建一个工厂类,它迭代tst变量,将值重新转换为基本对象并将其转储到tst2。但是,这个tst var可能包含数千个条目,这使得该解决方案变得不明智。

另一个选项是Apache Collections Transforms,但由于这些只是迭代器,我的收益并不多。

我有什么更优雅的东西可以用来降低通用性,或者Sun的泛型类型擦除概念只是注定了我。

3 个答案:

答案 0 :(得分:3)

您可以使用ImmutableMap.copyOf方法,并使用明确的约束:

ImmutableMap<String, Object> tst2 = ImmutableMap.<String, Object>copyOf(tst.asMap());

请注意,此doesn't necessarily copy the map - 在某些(很多)情况下,tst == tst2(它们是相同的引用)。

如果您绝对必须避免复制地图,则需要使用通配符类型,因为ImmutableMap<K, Object>ImmutableMap<K, Collection<Object>>不是相关类型:

ImmutableMap<String, ?> tst2 = tst.asMap();

值是通配符类型的事实不应影响您对地图值执行任何操作的能力Object

for (Map.Entry<String, ?> entry : tst2.entrySet()) {
  Object value = entry.getValue();
  //...
}

答案 1 :(得分:2)

它无法投射,但有一个简单的解决方法:

ImmutableMap<String, Object> tst2 =
    (ImmutableMap<String, Object>) (Object) tst.asMap();

这看起来可能有点健全:

    ImmutableListMultimap<String, Object> tst = ...
    ImmutableMap<String, ? extends Collection<Object>> asMap = tst.asMap();
    @SuppressWarnings("unchecked")
    ImmutableMap<String, Object> tst2 = (ImmutableMap<String, Object>) asMap;

通用系统并不完美(如果是,它会更复杂),有时候很难理解。由于不变性,上面未经检查的演员阵容是安全的:没有办法放入Object(这会违反Map<String, Collection<Object>>签名)。

答案 2 :(得分:0)

因此,一种不会产生任何编译警告的方法是使用ImmutableMap.copyOf而不是强制转换。这实际上不会执行副本,因为它可以检测到这是多余的,但需要ImmutableMap<? extends K, ? extends V>并返回ImmutableMap<K, V>

它仍然是一个恒定的时间操作,并且在表面下施放,但它不会产生警告。