Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
471 views
in Technique[技术] by (71.8m points)

java - Heterogeneous Container with two element of same type

I am reading Effective Java - Item 29. It talks about Heterogeneous container, in the example:

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);

    ....
}

This pattern parametrises the key instead of values, so you are not limited to a single type, unlike:

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

My question is: what if there are two elements of same type that needed to be added to the Map, i.e. two String, is this pattern still useful?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First, note that Item 29 is really about the general concept of using parameterized keys:

Sometimes, however, you need more flexibility. For example, a database row can have arbitrarily many columns, and it would be nice to be able to access all of them in a typesafe manner. Luckily there is an easy way to achieve this effect. The idea is to parameterize the key instead of the container.

The intent of this item is to demonstrate that you can use generics in more ways than just by parameterizing a type. The Heterogeneous Container pattern is simply an example of this technique. Admittedly, the item could make that point clearer with a better title like "Consider using parameterized methods to enforce type safety when working with arbitrary numbers of types".

The Heterogeneous Container pattern the item demonstrates is specifically for the case where you want to associate certain types with a particular instance of each type. Guava includes an implementation of this pattern with their ClassToInstanceMap type (more details). They also provide the more powerful TypeToInstanceMap that supports arbitrary generic types (e.g. List<String>) with an admittedly slightly more cumbersome API.

All of this is to say that there's nothing stopping you from creating a similarly structured class that supports multiple instances of a given type. We could easily take the ClassToInstanceMap API and create a ClassToInstanceMultimap type (extending Guava's 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 doesn't currently include such an interface, but the implementation of ClassToInstanceMap is pretty straightforward, so you could easily create your own ClassToInstanceMultimap implementations.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...