java ArrayList.remove(int) 与不同线程中的 ArrayList.remove(Object)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14467464/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ArrayList.remove(int) vs ArrayList.remove(Object) in different thread
提问by David T.
I have an ArrayList of Minion objects, and when a shield collides with a minion, I want to remove that minion from the ArrayList. However, I can only get it to work in 1 way, but not the other way. can anyone plz explain why?
我有一个 Minion 对象的 ArrayList,当盾牌与 Minion 碰撞时,我想从 ArrayList 中删除该 Minion。但是,我只能让它以一种方式工作,而不能以另一种方式工作。谁能解释一下为什么?
In all 3 cases, I'm using Android's Renderer's onDrawFrame() method... so I have no control over when it gets called. but here's the code for all 3 ways:
在所有 3 种情况下,我都使用 Android 的 Renderer 的 onDrawFrame() 方法......所以我无法控制它何时被调用。但这是所有 3 种方式的代码:
Method 1: (does not work)
方法一:(不起作用)
public void onDrawFrame(GL10 gl) {
List<Integer> indexesToRemove = new ArrayList<Integer>();
int len = minions.size();
for(int i=0; i<len; i++){
if( OverlapTester.overlapCircleRectangle( (Circle)shield1.bounds, (Rectangle)minions.get(i).bounds) ){ //this tests out to work just fine
indexesToRemove.add(i);
}
}
for(int i=indexesToRemove.size()-1; i>=0; i--){
minions.remove(indexesToRemove.get(i)); //<------ why doesn't this work?
}
}
the problem is that that last line minions.remove(indexesToRemove.get(i));
doesn't ACTUALLY remove the minions. it DOES get called, with the proper index. i've stepped through the debugger, ran it straight up, and the arraylist isn't modified at all. why is this? actually, in the debugger, that line "minions.remove(indexesToRemove.get(i));" gets called a bijillion times.
问题是最后一行minions.remove(indexesToRemove.get(i));
实际上并没有删除仆从。它确实被调用,并带有正确的索引。我已经通过调试器,直接运行它,并且根本没有修改数组列表。为什么是这样?实际上,在调试器中,该行“minions.remove(indexesToRemove.get(i));” 被称为 bijillion 次。
Method 2: (still does not work)
方法二:(还是不行)
public void onDrawFrame(GL10 gl) {
synchronized(minions){
List<Integer> indexesToRemove = new ArrayList<Integer>();
int len = minions.size();
for(int i=0; i<len; i++){
if( OverlapTester.overlapCircleRectangle( (Circle)shield1.bounds, (Rectangle)minions.get(i).bounds) ){ //this tests out to work just fine
indexesToRemove.add(i);
}
}
for(int i=indexesToRemove.size()-1; i>=0; i--){
minions.remove(indexesToRemove.get(i)); //<------ why doesn't this work?
}
}
}
In here, I thought... "oh maybe since it's not quite synchronized, the drawFrame sometimes gets called too many times and is accessing the arraylist at the wrong time and i need to lock it. but it still doesn't work. again, that line minions.remove(indexesToRemove.get(i));
gets called properly with the right index, but does NOT actually remove the object. i'm watching my shield on the screen slam right into the minion and nothing happens to the minion (it doesn't get removed from the arraylist)
在这里,我想......“哦,也许因为它不是很同步,所以有时 drawFrame 被调用了太多次并且在错误的时间访问了数组列表,我需要锁定它。但它仍然不起作用。再次, 该行minions.remove(indexesToRemove.get(i));
被正确的索引正确调用,但实际上并没有删除对象。我正在看着屏幕上的盾牌直接撞到小兵,小兵没有任何反应(它没有从数组列表中删除)
Method #3 (this actually works)
方法#3(这确实有效)
public void onDrawFrame(GL10 gl) {
ArrayList<Minion> colliders = new ArrayList<Minion>(minions);
int len = colliders.size();
for(int i=0; i<len; i++){
GameObject collider = colliders.get(i);
if(OverlapTester.overlapCircleRectangle((Circle)shield1.bounds, (Rectangle)collider.bounds)){
minions.remove(collider); // <---- why does THIS work instead?
}
}
}
this code works perfectly. the shield smacks the minion and the minion drops dead. as you can see here, the ONLY difference is that i'm using the overloaded ArrayList.remove(object)
method instead of removing by index. as in the line minions.remove(collider);
. why does THIS work ?
这段代码完美无缺。盾牌击中仆从,仆从倒地死亡。正如您在此处看到的,唯一的区别是我使用的是重载ArrayList.remove(object)
方法而不是按索引删除。就像在行中一样minions.remove(collider);
。为什么这有效?
can anyone please explain?
谁能解释一下?
on a side note, aside from storing another instance variable copy of the arraylist, is there a better way to manage ArrayList<Minion> colliders = new ArrayList<Minion>(minions);
?
附带说明一下,除了存储数组列表的另一个实例变量副本之外,还有更好的管理方法ArrayList<Minion> colliders = new ArrayList<Minion>(minions);
吗?
Note: both Shield and Minion are regular Java objects that have a rectangular shape as boundary. all that math checks out just fine. i've tested it in the debugger and the collision detection is accurate. I'm also updating the bounds/positions accurate in the onDrawFrame()
method.
注意:Shield 和 Minion 都是以矩形为边界的常规 Java 对象。所有的数学检查都很好。我已经在调试器中对其进行了测试,碰撞检测是准确的。我也在更新onDrawFrame()
方法中准确的边界/位置。
回答by Hyman
Because ArrayList
provides two methods that are:
因为ArrayList
提供了两种方法,它们是:
public E remove(int index)
public boolean remove(Object o)
When you invoke minions.remove(indexesToRemove.get(i))
, since indexesToRemove
is a List<Integer>
, the invocation is bound to the second signature in which you remove an element by directly specifying the object, auto-unboxing doesn't turn your Integer
into an int
so the element is not found and nothing happens.
当您调用minions.remove(indexesToRemove.get(i))
,因为indexesToRemove
是 a List<Integer>
,调用绑定到您通过直接指定对象删除元素的第二个签名,自动拆箱不会将您Integer
变成 an ,int
因此找不到该元素并且没有任何反应。
Try with: minions.remove((int)indexesToRemove.get(i))
so that static binding of the method is correctly applied.
尝试使用:minions.remove((int)indexesToRemove.get(i))
以便正确应用该方法的静态绑定。
回答by Gray
@Hyman's answer is correct. For posterity you should be using an Iterator
here that you can remove with insideyour loop:
@Hyman 的回答是正确的。对于后代,您应该使用Iterator
可以在循环内删除的此处:
// synchronization wrapper here
Iterator<Minion> iterator = minions.iterator();
while (iterator.hasNext()) {
Minion minion = iterator.next();
if( OverlapTester.overlapCircleRectangle(..., minion.bounds)) {
iterator.remove();
}
}
回答by Ryan
It's treating Integer as an object ref in the 1st two example, cast it to an int
它在第一个两个示例中将 Integer 视为对象 ref,将其转换为 int