具有两个相同类型元素的异构容器

时间:2013-12-31 21:22:59

标签: java map effective-java

我正在阅读有效的Java - 第29项。它讨论了异构容器,例如:

private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>();

public <T> void putFavirite(Class<T> type, T insance) {
    if(type == null) {
        throw new NullPointerException();
    }
    favorites.put(type, insance);

    ....
}

此模式参数化键而不是值,因此您不限于单一类型,不像:

 private Map<Integer, String> favorites ....    

我的问题是:如果有两个相同类型的元素需要添加到Map,即两个String,这个模式仍然有用吗?

2 个答案:

答案 0 :(得分:1)

首先,请注意,第29项实际上是关于使用参数化键的一般概念:

  

但是,有时您需要更多的灵活性。例如,数据库行可以有任意多列,并且能够以类型安全的方式访问所有列是很好的。幸运的是,有一种简单的方法可以达到这种效果。我们的想法是参数化而不是容器

此项目的目的是证明您可以通过参数化类型来更多地使用泛型。异构容器模式只是这种技术的一个例子。不可否认,该项目可以更清晰地使用更好的标题,例如“在使用任意数量的类型时,考虑使用参数化方法来强制执行类型安全”。

对于要将某些类型与每种类型的特定实例相关联的情况,项目演示的异构容器模式是具体Guava包含ClassToInstanceMap类型(more details)的此模式的实现。它们还提供功能更强大的TypeToInstanceMap支持任意泛型类型(例如List<String>),其中包含一个稍微繁琐的API。

所有这一切都是说,没有什么可以阻止你创建一个支持给定类型的多个实例的类似结构的类。我们可以轻松地使用ClassToInstanceMap API并创建ClassToInstanceMultimap类型(扩展Guava的Multimap API):

public interface ClassToInstanceMultimap<B> extends Multimap<Class<? extends B>, B> {
  /**
   * Returns the values the specified class is mapped to, or an empty collection if no
   * entries for this class is present. This will only return a value that was
   * bound to this specific class, not a value that may have been bound to a
   * subtype.
   */
  <T extends B> Collection<T> getInstances(Class<T> type);

  /**
   * Stores an entry mapping the specified class to the specified value. Does <i>not</i>
   *  associate this value with any of the class's supertypes.
   *
   * @return {@code true} if the method increased the size of the multimap, or
   * {@code false} if the multimap already contained the key-value pair and doesn't allow
   * duplicates
   */
  <T extends B> T putInstance(Class<T> type, T value);
}

Guava目前不包含这样的界面,但implementation of ClassToInstanceMap非常简单,因此您可以轻松创建自己的ClassToInstanceMultimap实现。

答案 1 :(得分:0)

如果您放置两个字符串,则第二个字符串将覆盖第一个字符串。所以只有在需要这种行为时它才有用。如果要在同一个键下存储更多对象,可以使用其他容器,例如:

Map<Class<?>, List<Object>>

或者您可以使用Guava中的MultiMap:http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Multimap.html

或者您可以从apache commons使用MultiMap:http://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/MultiMap.html