Java-将对象存储在遵循其类继承的层次结构中

Bri*_*ski 4 java

我需要存储很多属于不同类的对象:

ClassA {...}
ClassA1 extends ClassA {...}
ClassA2 extends ClassA {...}
ClassA2a extends ClassA2 {...}
ClassB {...}
Run Code Online (Sandbox Code Playgroud)

现在,我需要找到一种方法来存储所有这些对象,从而使我能够有效地获取属于特定类及其继承的子类的所有对象。例如,这个假想代码

getObjects(ClassA2)
Run Code Online (Sandbox Code Playgroud)

将返回属于ClassA2或ClassA2a的所有存储对象的列表。

我相信某种树集合将是合适的,但是我想不出任何实现它的方法。有任何想法吗?


(背景:我正在创建一个简单的Java游戏,其中需要管理大量的Sprite,而其中一些Sprite具有相似的属性。当我检查碰撞等事件时,我需要获取所有扩展EnemySprite和将他们的坐标与玩家的精灵进行比较。)

Mif*_*eet 5

有几种方法可以解决此问题。其中之一是,例如,以生成字符串一样ParentClass1:ChildClass2:ChildClass1:为每个对象,并把它们作为关键,TreeMap或者Trie你会然后遍历。

不过,这是一个更简单的解决方案。以下类包含从类到实现它的所有对象的映射。唯一的技巧是将一个对象添加到它所属的所有存储桶中:

public class HierarchyMap {
    private final Map<Class<?>, List<Object>> map = new HashMap<>();

    public void add(Object o) {
        Class<?> clazz = o.getClass();
        while (clazz != Object.class) {
            List<Object> list = map.computeIfAbsent(clazz, c -> new ArrayList<>());
            list.add(o);
            clazz = clazz.getSuperclass();
        }
    }

    public List<Object> getByClass(Class<?> clazz) {
        return map.get(clazz);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

public class A { public String toString() { return "A"; } }
public class B extends  A{ public String toString() { return "B"; } }
public class C extends  B { public String toString() { return "C"; } }
// ...
HierarchyMap hierarchyMap = new HierarchyMap();
hierarchyMap.add(new A());
hierarchyMap.add(new B());
hierarchyMap.add(new C());
System.out.println(hierarchyMap.getByClass(B.class)); 
// prints [B, C]
Run Code Online (Sandbox Code Playgroud)


小智 4

Mifeet 似乎确实回答了您的问题,但我怀疑您不应该尝试做您打算做的事情。为什么不只拥有所有可能发生碰撞的对象的主列表,然后根据需要使用过滤它instanceof

从概念上讲,这比您建议做的要容易得多,而且对效率的影响可能没有那么大。(一般来说,您可能会听到或已经听到过这样的口头禅:不要过早尝试优化。)

老实说,我不确定您是否意识到过滤EnemySprite也会获得其子类的所有对象实例。

public class CollisionChecker(){

   private List colliders;

   public CollisionChecker(){    
       colliders = new ArrayList<Object>();    
   }

   public void addCollider(Object o){
       colliders.add(o);
   }

   public List<EnemySprite> getEnemySprites(){
       List<EnemySprite> enemies = new ArrayList<EnemySprite>();
       for (Object o : colliders)
           if (o instanceof EnemySprite)
               enemies.add((EnemySprite)o);
       return enemies;        
   }     
}
Run Code Online (Sandbox Code Playgroud)