可以在同一列表的另一个迭代中迭代列表吗?

发布于 2024-11-03 06:25:56 字数 356 浏览 1 评论 0原文

我在 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);
    }
}

这一定是糟糕的编码,对吧?我将如何正确执行此嵌套迭代?

I have some objects in an ArrayList, and I want to perform collision detection and such. Is it okay to do something like:

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);
    }
}

That's gotta be terrible coding, right? How would I perform this nested iteration appropriately?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夜吻♂芭芘 2024-11-10 06:25:56

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

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

只要 getsDrunkAndRegretsHookingUpWith 方法不更改 people 列表,就没有问题。

You can iterate over the same list multiple times concurrently, as long as it's not being modified during any of the iterations. For example:

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

As long as the getsDrunkAndRegretsHookingUpWith method doesn't change the people list, this is all fine.

罪#恶を代价 2024-11-10 06:25:56

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

@Chris 的回答向您展示了一种更好的编码方法。


回复:OP评论

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

您不应该使用列表来存储粒子。如果您要对二维粒子进行建模,请使用四叉树。如果是 3 维,则为 八叉树

This is an example of the classic handshake problem. In a room full of n people, there are n choose 2 different possible handshakes. You can't avoid the quadratic runtime.

@Chris' answer shows you a better way to code it.


Re: OP comment

What I've been cooking up is some code where an event causes a particle to explode, which causes all nearby particles to explode...chain reaction. The objects are stored in one list and the non-exploded particles only explode if they are within a defined radius of an exploding ones. So I could dish up some conditionals to make it a bit faster, but still need the n^2 traversal.

You should not use a list to store the particles. If you're modeling particles in 2 dimentions, use a quadtree. If 3 dimensions, an octree.

画中仙 2024-11-10 06:25:56

如果您遇到以下情况,则可以减少迭代次数:

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

Number of iterations can be reduced if in you case:

  • A.getsDrunkAndRegretsHookingUpWith(B) implies B.getsDrunkAndRegretsHookingUpWith(A) too,
  • and A.getsDrunkAndRegretsHookingUpWith(A) will always be same for all elements

then instead of using iterator or foreach, you can take more traditional approach and exclude collision with itself and with the elements with withc comparison has already taken place.

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
    }
}
自在安然 2024-11-10 06:25:56

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

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

不必要地暴露迭代器当然不是糟糕的编程。按照 1 到 10 的糟糕编码风格评分,这只是 1 或 2。(任何告诉你其他情况的人最近都没有见过任何真正糟糕的编码......)

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

你原来的问题太做作,无法回答这个问题。

根据真实关系是什么,您也许能够利用对称性/反对称性或关联性来减少工作量。

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


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

That's gotta be terrible coding, right?

Most people would probably agree that if you were using Java 5+, and there was no particular need to expose the iterator objects, then you should simplify the code by using a "for each" loop. However, this should make no difference to the performance, and certainly not to the complexity.

Exposing the iterators unnecessarily is certainly not terrible programming. On a scale of 1 to 10 of bad coding style, this is only a 1 or 2. (And anyone who tells you otherwise hasn't seen any truly terrible coding recently ... )

So how to do n^2 over oneself?

Your original question is too contrived to be able to give an answer to that question.

Depending on what the real relation is, you may be able to exploit symmetry / anti-symmetry, or associativity to reduce the amount of work.

However, without that information (or other domain information), you can't improve on this solution.


For your real example (involving particles), you can avoid the O(N^2) comparison problem by dividing the screen into regions; e.g. using quadtrees. Then you iterate over points in the same and adjacent regions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文