更新这是我的明确答案:
您在索引、描述和与之关联的值类型之间存在静态关系。所以让我们在一个类中捕捉到这一点:
public class Key<VALUETYPE> {
private final Integer index;
private final String description;
private final Class<VALUETYPE> valueType;
public Key(final Integer index, final String description, final Class<VALUETYPE> valueType) {
super();
this.index = index;
this.description = description;
this.valueType = valueType;
}
public Integer getIndex() {
return index;
}
public String getDescription() {
return description;
}
public Class<VALUETYPE> getValueType() {
return valueType;
}
@Override
public int hashCode() {
return index.hashCode();
}
@Override
public boolean equals(final Object obj) {
if (this == obj) { return true; }
if (obj == null) { return false; }
if (getClass() != obj.getClass()) { return false; }
Key<?> other = (Key<?>) obj;
return index.equals(other.index);
}
}
我假设索引是键的唯一标识符,所以基于hashCode
它equals
。
现在您编写一个涵盖您的用例的访问器类:
public class MapAccessor {
private final Map<Integer, Key<?>> keyMap;
private final Map<Key<?>, Object> valueMap;
public MapAccessor(final Map<Integer, Key<?>> keysByIndex, final Map<Key<?>, Object> valueMap) {
this.keyMap = keysByIndex;
this.valueMap = valueMap;
}
public void put(final Integer index, final Object value) {
Key<?> key = keyMap.get(index);
if (key.getValueType().isInstance(value) || value == null) {
valueMap.put(key, value);
}
else {
throw new IllegalArgumentException("Wrong type of value for index " + index + ", expected: " + key.getValueType()
+ ", actual: " + value.getClass());
}
}
public <VALUETYPE> VALUETYPE get(final Key<VALUETYPE> key) {
return key.getValueType().cast(valueMap.get(key));
}
public Object get(final Integer index) {
Key<?> key = getKey(index);
return key == null ? null : get(key);
}
public Key<?> getKey(final Integer index) {
return keyMap.get(index);
}
public String getDescription(final Integer index) {
Key<?> key = getKey(index);
return key == null ? null : key.getDescription();
}
}
或者,您可以将其放在子类中,HashMap<Key<?>, Object>
而不是委托给它。
让我们演示如何使用上述内容。请注意,对于按索引查找,强制转换是不可避免的。
public class ExampleUsage {
private static final Key<String> NAME = new Key<>(1, "Name", String.class);
private static final Key<Integer> AGE = new Key<>(2, "Age", Integer.class);
private static final Map<Integer, Key<?>> keysByIndex = buildKeysByIndex(NAME, AGE);
public static void main(final String... args) {
Map<Key<?>, Object> valueMap = new HashMap<>();
MapAccessor accessor = new MapAccessor(keysByIndex, valueMap);
accessor.put(1, "Jasmine");
String nameByIndex = (String) accessor.get(1); // returns "Jasmine", cast can't be avoided
String nameByKey = accessor.get(NAME); // returns "Jasmine", no cast necessary
Key<?> nameKeyByIndex = accessor.getKey(1); // returns NAME
String nameDescriptionByIndex = accessor.getDescription(1); // returns "Name"
accessor.put(2, 32);
Integer ageByIndex = (Integer) accessor.get(2); // returns 32, cast can't be avoided
Integer ageByKey = accessor.get(AGE); // returns 32, no cast necessary
Key<?> ageKeyByIndex = accessor.getKey(2); // returns AGE
String ageDescriptionByIndex = accessor.getDescription(2); // returns "Age"
}
private static Map<Integer, Key<?>> buildKeysByIndex(final Key<?>... keys) {
Map<Integer, Key<?>> keyMap = new HashMap<Integer, Key<?>>();
for (Key<?> key : keys) {
keyMap.put(key.getIndex(), key);
}
return Collections.unmodifiableMap(keyMap);
}
}