也许我在这里想错了,但是我想说我想要返回一堆不同类型的对象。例如很多人,个人资料,账户。我想把它们放在一个地图中,其中一个键就像Person.class,值将是一个Person实例列表。首先我想到了一个EnumMap,但是为什么我要为类列表创建一个ENUM,如果我能以某种方式自己使用这些类呢?
我试图用泛型来达到目标,但无法绕过定义。
这甚至可能吗?或者我在想一个糟糕的设计?
我可以提供不同的方法来检索部分结果。或者创建一个可以容纳它的类。但是如果我想在将来使用更多的类,Map会更灵活。
编辑:
我得到了一些答案,这似乎没有具体说明我在寻找什么,所以澄清:
我想要类似的东西:
{
Person.class : [person1Instance, person2Instance,...],
Account.class : [account1Instance, account2Instance, account3Instance, ...],
Profile.class : [profile1Instance...]
}
我想避免施法。以某种方式使用密钥应该为项目列表定义类型(安全)的事实。
答案 0 :(得分:3)
我已在TypedMap
:http://blog.pdark.de/2010/05/28/type-safe-object-map/
以下是一些演示代码:
TypedMap map = new TypedMap();
String expected = "Hallo";
map.set( KEY1, expected );
String value = map.get( KEY1 ); // Look Ma, no cast!
assertEquals( expected, value );
List<String> list = new ArrayList<String> ();
map.set( KEY2, list );
List<String> valueList = map.get( KEY2 ); // Even with generics
assertEquals( list, valueList );
魔法在关键:
final static TypedMapKey<String> KEY1 = new TypedMapKey<String>( "key1" );
final static TypedMapKey<List<String>> KEY2 = new TypedMapKey<List<String>>( "key2" );
要解决您的问题,您需要为要在地图中保存的不同类型创建密钥:
TypedMapKey<List<Account>> ACCOUNTS = new TypedMapKey<List<Account>>( "ACCOUNTS" );
然后你需要通常的get / create代码:
public <T> List<T> getList( TypedMapKey<List<T>> key ) {
List<T> result = map.get(key);
if(null == result) {
result = new ArrayList<T>();
map.put(key, result);
}
return result;
}
允许您使用以下方式访问列表:
List<Account> accounts = getList(ACCOUNTS);
答案 1 :(得分:1)
不允许使用不同类型的对象,因为在检索它们时我们遇到问题,我们不知道会出现什么类型的对象。
这是我的建议:
制作地图:
Map<Object, String> map = new HashMap<Object, String>();
让我们提出一些值:
Person p = new Person();
map.put(p, "Person");
Account a = new Account();
map.put(a, "Account");
假设您将传递不同的对象。
在检索这样的事情时:
for(Entry<Object, String> entry : map.entrySet()) {
String choiceClassName = entry.getValue();
switch(choiceClassName) {
case "Person" : Person p = (Person) entry.getKey();
break;
case "Account" : Account a = (Account) entry.getKey();
break;
}
}
答案 2 :(得分:0)
你不需要任何枚举。您可以使用instanceof来检查对象的类型。这就是我通常的做法,但我对其他人的其他答案感到好奇。
通常我只使用一个父类型和我的地图所需的通用方法(通常是一个接口)。 但有时我会使用这种方法,因为我真的不知道用户操作会将什么放入地图。
以此地图为例:
HashMap<String,Object> stuff = new HashMap<String,Object>();
stuff.add("joe",new Person());
stuff.add("new york", new City());
Iterator it = stuff.iterator();
while(it.hasNext()) {
Object obj = it.next();
if(obj instanceof Person) {
Person p = (Person)obj;
}
if(obj instanceof City) {
City c = (City)obj;
}
}
答案 3 :(得分:0)
最后,我使用来自tobias_k comment的提示创建了我自己的TypedMultimap。
我创建了这个类:
import com.google.common.collect.ForwardingMultimap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import java.util.Collection;
/**
*
* @author mimkorn
*/
public class TypedMultimap extends ForwardingMultimap<Class, Object> {
private final HashMultimap<Class, Object> delegate;
public TypedMultimap() {
this.delegate = HashMultimap.create();
}
// IMPORTANT PART
public <T> Collection<T> getSafely(Class<T> key) {
return (Collection<T>) delegate().get(key);
}
public <T> boolean putSafely(
Class<T> key, T value) {
return delegate.put(key, value);
}
// TILL HERE
// CONVENIENCE
public <T> boolean putSafely(T value) {
return delegate.put(value.getClass(), value);
}
// TILL HERE
@Override
public Collection<Object> get(Class key) {
return getSafely(key);
}
@Override
public boolean put(Class key, Object value) {
return putSafely(key, value);
}
@Override
protected Multimap<Class, Object> delegate() {
return delegate;
}
}
编辑:现在你可以放(new SomeClass());它会将它放入映射中,在SomeClass.class下映射它。这样您只需添加数据而无需关心类,地图将为您排序。然后,您可以使用<T> Collection<T> getSafely(Class<T> key)
现在,当您调用getSafely或putSafely时,它会为您检查类型。缺点是,用户以某种方式需要知道,他应该使用单个参数put方法添加数据。此外,只有getSafely和putSafely,将检查编译时错误。
现在你可以这样做:
TypedMultimap typedMultimap = new TypedMultimap();
typedMultimap.putSafely(new ExportThing("prvý"));
typedMultimap.putSafely(new ExportThing("druhý"));
typedMultimap.putSafely(ExportThing.class, new ExportThing("prvý"));
typedMultimap.putSafely(new ExportPhoneNumber("prvý"));
typedMultimap.putSafely(ExportPhoneNumber.class, new ExportPhoneNumber("druhý"));
Collection<ExportPhoneNumber> safely = typedMultimap.getSafely(ExportPhoneNumber.class);
for (ExportPhoneNumber safely1 : safely) {
System.out.println(safely1.getPhoneNumber());
}
将返回:
druhý
prvý
尝试做
typedMultimap.putSafely(ExportThing.class, new ExportPhoneNumber("prvý"));
将导致编译时错误。
这是一个有点Map&gt;。如果您需要地图&gt;例如,用作代理ArrayListMultimap而不是HashMultimap