【问题标题】:Is it okay to iterate over a list within another iteration of the same list?在同一个列表的另一个迭代中迭代一个列表是否可以?
【发布时间】:2011-04-23 04:19:52
【问题描述】:

我在 ArrayList 中有一些对象,我想执行碰撞检测等。可以这样做吗:

List<Person> A;
iterA0 = A.iterator();
while (iterA0.hasNext()) {
    Person A = iterA.next();
    iterA1 = A.iterator();
    while (iterA1.hasNext()){
        Person B = iterA1.next();
        A.getsDrunkAndRegretsHookingUpWith(B);
    }
}

那一定是很糟糕的编码,对吧?我将如何适当地执行这个嵌套迭代?

【问题讨论】:

  • 回复:你的第二个问题,见stackoverflow.com/editing-help
  • 我几分钟前去了那里并搜索了“逃生”,但没有成功。
  • A.getsDrunkAndRegretsHookingUpWith(B) 是否等同于 B.getsDrunkAndRegretsHookingUpWith(A)?
  • 我确信有很多算法可以处理碰撞检测,它们利用各种不同的技巧来提高速度。
  • 顺便说一句,当我喝醉时,我讨厌它并且后悔与自己挂钩。

标签: java iterator


【解决方案1】:

您可以同时对同一个列表进行多次迭代,只要它在任何迭代期间都没有被修改。例如:

List<Person> people = ...;
for (Person a : people) {
    for (Person b : people)
        a.getsDrunkAndRegretsHookingUpWith(b);
}

只要getsDrunkAndRegretsHookingUpWith 方法不改变people 列表,这一切都很好。

【讨论】:

    【解决方案2】:

    这是经典握手问题的一个示例。在一个满是n 人的房间里,有n 选择2 不同可能的握手。你无法避免二次运行时间。

    @Chris' answer 向您展示了一种更好的编码方式。


    回复:OP 评论

    我一直在编写一些代码,其中事件导致粒子爆炸,这导致所有附近的粒子爆炸......连锁反应。对象存储在一个列表中,未爆炸的粒子仅在它们处于爆炸粒子的定义半径内时才会爆炸。所以我可以提出一些条件来让它更快一点,但仍然需要 n^2 遍历。

    您应该使用列表来存储粒子。如果您要在二维中建模粒子,请使用quadtree。如果是 3 维,则为 octree

    【讨论】:

      【解决方案3】:

      如果在您的情况下,可以减少迭代次数:

      • A.getsDrunkAndRegretsHookingUpWith(B) 也暗示B.getsDrunkAndRegretsHookingUpWith(A)
      • A.getsDrunkAndRegretsHookingUpWith(A)对于所有元素总是相同的

      然后,您可以采用更传统的方法,而不是使用迭代器或 foreach,并排除与自身的冲突以及与已经发生过 withc 比较的元素的冲突。

      List<Person> people;
      for (int i=0; i<people.size(); i++){
          a = people.get(i);
          for (int j=i+1; j<people.size();j++){ // compare with next element and onwards in the list
              a.getsDrunkAndRegretsHookingUpWith(people.get(j)); // call method
          }
      }
      

      【讨论】:

        【解决方案4】:

        那一定是很糟糕的编码,对吧?

        大多数人可能会同意,如果您使用的是 Java 5+,并且没有特别需要公开迭代器对象,那么您应该使用“for each”循环来简化代码。但是,这应该不会影响性能,当然也不会影响复杂性。

        不必要地暴露迭代器当然不是糟糕的编程。在 1 到 10 的糟糕编码风格的范围内,这只是 1 或 2。(而且任何告诉你其他情况的人最近都没有看到任何真正糟糕的编码......)

        那么如何对自己做n^2呢?

        您最初的问题过于人为,无法回答该问题。

        根据真正的关系是什么,您可以利用对称/反对称或关联性来减少工作量。

        但是,如果没有该信息(或其他域信息),您将无法改进此解决方案。


        对于您的真实示例(涉及粒子),您可以通过将屏幕划分为区域来避免O(N^2)的比较问题;例如使用四叉树。然后迭代相同和相邻区域中的点。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-08-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-07
          • 1970-01-01
          • 2016-05-14
          相关资源
          最近更新 更多