3

以下场景要解决:我需要创建一个类,该类将根据给定的 id+classtype 返回或存储水果列表。所以我在质疑自己,Collection使用哪个以及是否能够将所有水果列表存储在同一个Collection中以用于 simplecity。我决定HashMap尝试一次存储所有列表,因为键值原则听起来对我的用例很熟悉,只是它可能需要更复杂的键,因为我需要两个方面(在我的情况下是 id 和水果类),以识别值。

所以我创建了一个自己的关键对象:

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.
}

创建 a 后Map<FruitKey, List<? extends Fruits>>, put 可以正常工作,但是当然,当我尝试将 FruitLists 从 Map 中取出时,我无法保证特定的水果类型,而必须转换结果:

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 已经包含在 key 中,我不知何故认为我可以将这些与 maps 值联系起来,但不幸的是我没有成功,没有将 map 专门用于特殊水果。您是否有机会避免我的 typesafe/classcast 问题,或者可以推荐另一种收集类型来实现我的目标?当然我可以为每个水果创建一个地图,但是因为那里有很多好吃的水果,我尽量避免它,因为我总是不得不在它们之间有所不同。

简而言之,这就是我想要的:

List<Apple> apples = SomeCollection.get( Key(id, Apple.class) );

之所以有 Id,是因为在同一个 Map 中可以有多个 Apples 列表,以及其他 Fruits 的多个 Lists。

4

1 回答 1

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篮子的 a 并带有适当的hashCodeand equals

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);
}
于 2012-11-09T12:16:02.757 回答