以下场景要解决:我需要创建一个类,它将返回或存储一个Fruit of Fruits,具体取决于给定的id + classtype。所以我在质疑自己,Collection
要使用,如果我能够将所有水果清单存储在同一个Collection
中以获得简单性。我试图单独HashMap
尝试存储所有列表,因为键值原则听起来很熟悉我的用例,只是它可能需要一些更复杂的键,因为我需要两个方面(在我的case id和fruits class),以识别价值。
所以我创建了一个自己的密钥对象:
class FruitKey
{
int id;
Class<? extends Fruits> type;
public FruitKey( int id, Class<? extends Fruits> type )
{
this.id = id;
this.type = type;
}
//equals, hashcode, etc.
}
在创建Map<FruitKey, List<? extends Fruits>>
之后,推杆工作完美无缺,但当然当我尝试将我的FruitLists从地图中取出时,我无法保证特定的水果类型并且必须投射结果:
public static void main( String[] args )
{
Map<FruitKey, List<? extends Fruits>> fruitMap = new HashMap<>();
Apple oneApple = new Apple();
List<Apple> manyApples = new ArrayList<>();
manyApples.add( oneApple );
fruitMap.put( new FruitKey( 1, Apple.class ), manyApples);
//Any way to avoid typesafty and cast?
List<Apple> myApples = (List<Apple>) fruitMap.get( new FruitKey( 1, Apple.class ) );
}
由于classtype已经包含在键中,我不知何故认为我可以将这些与map值连接起来,但不幸的是我没有成功,没有将地图专用于特殊的水果。你有没有机会避免我的类型/类别广播问题,或者可以推荐另一种收集类型来实现我的目标?当然我可以为每个水果创建一个地图,但由于那里有很多yummi水果,我试图避免它,因为我总是要在它们之间有所区别。
简而言之,这就是我想要的:
List<Apple> apples = SomeCollection.get( Key(id, Apple.class) );
同样存在Id的原因是,因为在同一个地图中可以有几个苹果列表,以及其他几个水果列表。
答案 0 :(得分:1)
您可以使用异类容器。您仍然需要在容器内部进行转换,但由于通用方法和类的final
,转换是安全的,您可以禁止警告。
这是安全的,因为通用put
确保您永远不会放置任何会使演员失败的内容。
public final class SomeCollection {
private Map<FruitKey<? extends Fruits>, List<? extends Fruits>> fruitMap = new HashMap<>();
//safe cast
@SuppressWarnings("unchecked")
public <T extends Fruits> List<T> get(FruitKey<T> key)
{
return (List<T>) fruitMap.get(key);
}
public <T extends Fruits> void put(FruitKey<T> key, List<T> fruits)
{
fruitMap.put(key, fruits);
}
}
键入FruitKey
class FruitKey<T extends Fruits>
{
int id;
Class<T> type;
public FruitKey( int id, Class<T> type )
{
this.id = id;
this.type = type;
}
}
您还可以在Key<T>
中创建一个内部类SomeCollection
,其中包含一个FruitKey
的购物篮以及相应的hashCode
和equals
。< / p>
private Map<Key<? extends Fruits>, List<? extends Fruits>> fruitMap = new HashMap<>();
//safe cast
@SuppressWarnings("unchecked")
public <T extends Fruits> List<T> getBasket(T fruit)
{
Key<T extends Fruit> = new Key<T>(fruit.getBasketId());
return (List<T>) fruitMap.get(key);
}
//or
//safe cast
@SuppressWarnings("unchecked")
public <T extends Fruits> List<T> getBasket(Class<T> klass, FruitKey key)
{
Key<T extends Fruit> = new Key<T>(key);
return (List<T>) fruitMap.get(key);
}
public <T extends Fruits> void addToBasket(T fruit, List<T> fruits)
{
Key<T extends Fruit> = new Key<T>(fruit.getBasketId());
fruitMap.put(key, fruits);
}