2

我正在阅读Effective Java - Item 29。它讨论了Heterogeneous container,在示例中:

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,这种模式仍然有用吗?

4

2 回答 2

1

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

但是,有时您需要更大的灵活性。例如,一个数据库行可以有任意多列,如果能够以类型安全的方式访问所有列,那就太好了。幸运的是,有一种简单的方法可以实现这种效果。这个想法是参数化key而不是container

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

该项目演示的异构容器模式专门用于您希望将某些类型与每种类型的特定实例相关联的情况。Guava包含了这种模式的实现及其ClassToInstanceMap类型(更多细节)。它们还提供了更强大TypeToInstanceMap的支持任意泛型类型(例如List<String>)的功能,但 API 确实略显繁琐。

所有这一切都是说,没有什么能阻止您创建一个支持给定类型的多个实例的类似结构的类。我们可以轻松地获取ClassToInstanceMapAPI 并创建一个ClassToInstanceMultimap类型(扩展 Guava 的MultimapAPI):

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 目前不包含这样的接口,但其实现ClassToInstanceMap非常简单,因此您可以轻松创建自己的ClassToInstanceMultimap实现。

于 2017-07-23T00:14:50.567 回答
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

于 2013-12-31T21:54:21.393 回答