我有一个 Sprite 类:
public class Sprite {
public static ArrayList<Sprite> sprites = null;
private Texture texture = null;
public Sprite(Texture texture) {
sprites.add(this);
this.texture = texture;
}
public void render(SpriteBatch batch) {
batch.draw(texture);
}
public void dispose() {
sprites.remove(this);
}
}
在我创建任何 Sprite 之前,我确保 Sprite 类具有对将要渲染的 Sprite 池的引用:
public class Main extends ApplicationAdapter {
private static ArrayList<Sprite> sprites = new ArrayList<Sprite>();
public Main() {
Sprite.sprites = sprites;
new Sprite("texture.png");
}
@Override
public void render(SpriteBatch batch) {
for (int i = 0; i < sprites.size(); i++)
sprites.get(i).render(batch);
}
}
所以现在当我创建一个新的 sprite 时,它会自动呈现,而无需我手动将它添加到 ArrayList 中。
问题是 sprite 可以在 for 循环运行期间被释放,因此某些 sprite 不会在该特定帧渲染。
我不想向后循环遍历项目,例如:
for (int i = sprites.size() - 1; i >= 0; i--)
sprites.get(i).render(batch);
因为这会使我的 sprite 乱序(应该在顶部的 sprite 将被覆盖)。
到目前为止,我唯一的解决方案是使用另一个 ArrayList 来跟踪要处理的对象,例如:
public class Sprite {
public static ArrayList<Sprite> sprites = null, garbage = null;
//everything else the same
public void dispose() {
garbage.add(this);
}
}
然后在渲染过程中,我首先从 Sprite 中移除所有垃圾,然后渲染 Sprite :
for (int i = 0; i < garbage.size(); i++)
sprites.remove(garbage.get(i));
garbage.clear();
for (int i = 0; i < sprites.size(); i++)
sprites.get(i).render(batch);
这个方法可行,但我感觉效率不高。 (有两个数组列表?然后做两个 for 循环?)
有什么方法可以循环遍历 Sprites 而不会在处置 Sprite 时跳过 Sprite?我不想向后循环 Sprites,因为它会打乱顺序。
我现在已经使用同步列表对此进行了测试,但我无法使其正常工作。
Testable code , (与 java.util.ConcurrentModificationException
)
import java.util.*;
class Ideone {
public static class Sprite {
public static List<Sprite> sprites = null;
public int age = 0;
public Sprite() {
synchronized(sprites) {
sprites.add(this);
}
}
public void render() {
age++;
if (age > 30)
dispose();
}
public void dispose() {
synchronized(sprites) {
sprites.remove(this);
}
}
}
private static List<Sprite> sprites = Collections.synchronizedList(new ArrayList<Sprite>());
public static void main(String[] args) {
Sprite.sprites = sprites;
new Sprite();
new Sprite();
for (int i = 0; i < 60; i++)
render();
}
public static void render() {
synchronized(sprites) {
Iterator<Sprite> iterator = sprites.iterator();
while (iterator.hasNext())
iterator.next().render();
}
}
}
最佳答案
首先,如果从多个线程访问sprites
列表,您需要同步访问它或使用线程安全数据结构(例如 CopyOnWriteArrayList 或 CopyOnWriteArraySet)。
Sprite.dispose
可以直接从 sprites
中移除自己。
关于java - 如何循环在循环期间发生变化的 ArrayList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30488297/