0

我想实现 Map 接口,但将 K 和 V 绑定到接口)。然而,鉴于 Java 集合 API,特别是 MAP 接口,使用 Object 而不是泛型类型 K 和 V,将方法参数限制在最低限度。举例来说,接口指定:public boolean containsValue(Object value)而不是public boolean containsValue(V value). 在这种情况下,我不能依赖编译器类型安全。

为了清楚起见,我想实现以下内容:

class MyMap< K , V extends ValueInterface> implements Map<K,V>

但是,我需要实现以下方法:

@Override
public boolean containsValue(Object value) {
      // What to do here? 
      ValueInterface v = (ValueInterface ) v; 
      v.getWhatIWant().andDoThing(); 
      // Follow on... 
}

在这种情况下,我有哪些选择和/或最佳实践?

4

2 回答 2

1

This is the interface contract of Map - as such you must implement the contract as it stands.

However, let me suggest two reasons why the design of this part of the Map is a good thing:

i) The Map contract is that you can get values from the map under the following circumstances:

if this map contains a mapping from a key k to a value v such that (key==null ? k==null : key.equals(k)), then this method returns v; otherwise it returns null. (There can be at most one such mapping.)

or equivalently, and specific to your question about containsKey(Object key):

Returns true if this map contains a mapping for the specified key. More formally, returns true if and only if this map contains a mapping for a key k such that (key==null ? k==null : key.equals(k)). (There can be at most one such mapping.)

As such, you are not concerned about typing, but about equality.

ii) This is really just the same point, but consider the following:

Map<String, Integer> map = new HashMap<>();
String key = "A Key";
Integer value = 1;
map.put(key, value);

Object objectKey = key; // this is the same key object, but it is typed as Object
map.containsKey(objectKey); // what would you want/expect this to return?
map.get(objectKey); // ...or this?

As such, with regard to your implementation of Map, I would not advise just casting the Object key (you'll get a runtime exception...). How you decide to implement it will depend on your design. Let us imagine that you're storing the keys and values in typed lists... then you would be advised to check the instanceof the Object key before casting:

public boolean containsKey(Object key) {
  if (key instanceof K) {
    // do your thing...
  } else {
    return false;
  }
}

Note that instanceof checks the type of the underlying object, not its declared type, so:

String key = "A Key";
Object objectKey = key;
boolean isString = (objectKey instanceof String); // is true

Really, I would suggest that rather than asking how to force something that goes against the Map contract, you want to be asking the question "why is the contract that way?"...

于 2013-08-27T22:17:01.017 回答
0

如果要实现 Map<K,V>,则需要实现接口中的所有方法。

您可以扩展 AbstractMap<K,V>和覆盖抽象方法,以及您想要自定义行为的任​​何非抽象方法(只要您不违反Map合同)。

于 2013-08-27T21:37:04.310 回答