1

我正在用 Java 构建一个新的实体系统。我想知道我提出的方法是否会导致任何问题,无论是架构方面还是性能方面。

我想:

...

for (Entity entity : entities)
{
    for (Entry<String, Component> entry : entity.components.entrySet()) //collection is a Map
    {
        Component component = entry.getValue();
        component.update(deltaTime);
    }
}

...

与不受欢迎的替代方案相比:

...


for (Entity entity : entities)
{
    if (entity.componentA != null)
        entity.componentA.update(deltaTime);

    if (entity.componentB != null)
        entity.componentB.update(deltaTime);

    //etc. for as many components as the entity has. Finite, but possibly many.
}

...

对于第一种方法,我想到了一些关于 HashMap 方法的事情:

  • 我会避免不必要的条件(当成千上万的实体被update()调用时,这很重要);
  • 读取访问时间平均为 O(1)(您唯一可能无法获得的时间是在哈希冲突中);
  • HashMap.entrySet()必须调用以使用 for-each 语法遍历集合。正如我从文档中了解到的那样,“集合 [set] 由地图支持”。但是,这并不能告诉我 HashMap 是否在内部创建集合,每次都entrySet()被调用。
4

2 回答 2

2

读取访问时间平均为 O(1)(您唯一可能无法获得的时间是在哈希冲突中);

在入口集上的 for each 循环中,您不需要调用map.get().

但是,这并不能告诉我 HashMap 是否在内部创建集合,每次调用 entrySet()。

不,它不会每次都创建一个新集。


您应该编写最干净、最容易阅读和维护的代码。如果性能不够好(即您已经分析了您的应用程序并确定性能问题是由于该部分代码引起的),请开始优化。

==> 为每个循环使用一个。

于 2012-07-18T14:39:58.193 回答
1

第一个版本几乎肯定会是最好的设计:

  • 更通用的代码 - 涵盖所有可能的组件配置
  • 更简洁的代码和可维护性 - 避免所有条件
  • 运行时更灵活——您可以动态更改组件列表
  • 快速 - 假设 entity.components 是一个具有良好迭代器的合理数据结构,每个组件应该是 O(1)

如果您真的关心性能并且已经分析出这是一个重要的特殊情况,您可能需要考虑ComponentList为 entity.components 编写一个自定义数据结构(例如),这将有一个额外的方法updateAll(deltaTime)来有效地为所有包含的组件。这有几个优点:

  • 您可以避免分配 Iterator 对象(如果您使用 HashMap 或 ArrayList 会发生这种情况)
  • 您可以通过专注于 Component 类型来避免一些不必要的强制转换
于 2012-07-18T14:47:59.903 回答