可以在同一列表的另一个迭代中迭代列表吗?
我在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以同时多次迭代同一个列表,只要它在任何迭代期间都没有被修改。例如:
只要
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:
As long as the
getsDrunkAndRegretsHookingUpWith
method doesn't change thepeople
list, this is all fine.这是经典握手问题的一个例子。在一个充满
n
人的房间里,有n
种选择2
种不同的可能的握手方式。你无法避免二次运行时间。@Chris 的回答向您展示了一种更好的编码方法。
回复:OP评论
您不应该不使用列表来存储粒子。如果您要对二维粒子进行建模,请使用四叉树。如果是 3 维,则为 八叉树。
This is an example of the classic handshake problem. In a room full of
n
people, there aren
choose2
different possible handshakes. You can't avoid the quadratic runtime.@Chris' answer shows you a better way to code it.
Re: OP comment
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.
如果您遇到以下情况,则可以减少迭代次数:
A.getsDrunkAndRegretsHookingUpWith(B)
也意味着B.getsDrunkAndRegretsHookingUpWith(A)
,A.getsDrunkAndRegretsHookingUpWith(A)
对于所有元素总是相同的,那么您可以采取更传统的方法,而不是使用迭代器或 foreach,并排除与自身以及与已经发生 withc 比较的元素的碰撞。
Number of iterations can be reduced if in you case:
A.getsDrunkAndRegretsHookingUpWith(B)
impliesB.getsDrunkAndRegretsHookingUpWith(A)
too,A.getsDrunkAndRegretsHookingUpWith(A)
will always be same for all elementsthen 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.
大多数人可能会同意,如果您使用的是 Java 5+,并且没有特别需要公开迭代器对象,那么您应该通过使用“foreach”循环来简化代码。然而,这应该不会影响性能,当然也不会影响复杂性。
不必要地暴露迭代器当然不是糟糕的编程。按照 1 到 10 的糟糕编码风格评分,这只是 1 或 2。(任何告诉你其他情况的人最近都没有见过任何真正糟糕的编码......)
你原来的问题太做作,无法回答这个问题。
根据真实关系是什么,您也许能够利用对称性/反对称性或关联性来减少工作量。
但是,如果没有该信息(或其他域信息),您就无法改进此解决方案。
对于您的真实示例(涉及粒子),您可以通过将屏幕划分为多个区域来避免
O(N^2)
比较问题;例如使用四叉树。然后迭代相同和相邻区域中的点。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 ... )
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.