我需要一个数据结构来存储不同类型的 objects.EgString
和Boolean
其他类。
是否使用Map<String, Object>
where 使用密钥获得相应的对象,假设您知道如何将其转换为一个好习惯?
有更好的解决方案吗?
问问题
539 次
2 回答
5
PropretyHolder
这是我前段时间写的一个完美的用例。你可以在我的博客上详细阅读它。我开发它时考虑到了不变性,请随时根据您的需要进行调整。
一般来说,如果你想从 Java 中的类型安全中获益,你需要知道你的密钥。我的意思是-几乎不可能开发出密钥来自外部源的类型安全解决方案。
这是一个知道其值类型的特殊键(它不完整,请下载完整版本的源代码):
public class PropertyKey<T> {
private final Class<T> clazz;
private final String name;
public PropertyKey(Class<T> valueType, String name) {
this.clazz = valueType;
this.name = name;
}
public boolean checkType(Object value) {
if (null == value) {
return true;
}
return this.clazz.isAssignableFrom(value.getClass());
}
... rest of the class
}
然后你开发一个利用它的数据结构:
public class PropertyHolder {
private final ImmutableMap<PropertyKey<?>, ?> storage;
/**
* Returns value for the key of the type extending-the-one-declared-in-the {@link PropertyKey}.
*
* @param key {@link PropertyKey} instance.
* @return Value of the type declared in the key.
*/
@SuppressWarnings("unchecked")
public <T extends Serializable> T get(PropertyKey<T> key) {
return (T) storage.get(key);
}
/**
* Adds key/value pair to the state and returns new
* {@link PropertyHolder} with this state.
*
* @param key {@link PropertyKey} instance.
* @param value Value of type specified in {@link PropertyKey}.
* @return New {@link PropertyHolder} with updated state.
*/
public <T> PropertyHolder put(PropertyKey<T> key, T value) {
Preconditions.checkNotNull(key, "PropertyKey cannot be null");
Preconditions.checkNotNull(value, "Value for key %s is null",
key);
Preconditions.checkArgument(key.checkType(value),
"Property \"%s\" was given "
+ "value of a wrong type \"%s\"", key, value);
// Creates ImmutableMap.Builder with new key/value pair.
return new PropertyHolder(filterOutKey(key)
.put(key, value).build());
}
/**
* Returns {@link Builder} with all the elements from the state except for the given ket.
*
* @param key The key to remove.
* @return {@link Builder} for further processing.
*/
private <T> Builder<PropertyKey<? extends Serializable>, Serializable> filterOutKey(PropertyKey<T> key) {
Builder<PropertyKey<? extends Serializable>, Serializable> builder = ImmutableMap
.<PropertyKey<? extends Serializable>, Serializable> builder();
for (Entry<PropertyKey<? extends Serializable>, Serializable> entry : this.storage.entrySet()) {
if (!entry.getKey().equals(key)) {
builder.put(entry);
}
}
return builder;
}
... rest of the class
}
我在这里省略了很多不必要的细节,如果有不清楚的地方请告诉我。
于 2012-09-14T09:07:44.197 回答
2
Atypesafe heterogeneous container
可用于此目的:
import java.util.HashMap;
import java.util.Map;
public class Container {
private Map<Class<?>, Object> container = new HashMap<Class<?>, Object>();
public <T> void putElement(Class<T> type, T instance) {
if (type == null) {
throw new NullPointerException("Type is null");
}
//container.put(type, instance); // 'v1'
container.put(type, type.cast(instance)); // 'v2' runtime type safety!
}
public <T> T getElement(Class<T> type) {
return type.cast(container.get(type));
}
public static void main(String[] args) {
Container myCont = new Container();
myCont.putElement(String.class, "aaa");
myCont.putElement(Boolean.class, true);
myCont.putElement(String[].class, new String[] {"one", "two"});
System.out.println(myCont.getElement(String.class));
System.out.println(myCont.getElement(String[].class)[1]);
}
}
限制:这个容器的形式只能存储一种实例/对象类型。
您可以通过使用动态转换putElement()
来实现运行时类型安全。这将增加额外的开销。
例如:尝试将原始类对象传递给容器。注意异常发生的位置:
Class raw = Class.forName("MyClass");
myCont.putElement(raw, "aaa"); //ClassCastException if using 'v2'
System.out.println(myCont.getElement(raw)); //ClassCastException if using 'v1'
于 2012-09-14T09:34:45.130 回答