繁体   English   中英

遍历Hashmap会导致崩溃

[英]Iterating over Hashmap causes crash

我注意到我的应用最近崩溃了很多,调试之后我发现,当我遍历哈希映射时,一些随机崩溃了。

我像这样遍历它们:

for (Map.Entry<Point, Particle> entry : spawned.entrySet()) {
                entry.getValue().Draw(canvas);
        } 

导致: 在此处输入图片说明

之后,我尝试使用迭代器对它们进行迭代,如下所示:

        Iterator<Map.Entry<Point, Particle>> entries = spawned.entrySet().iterator();
    while (entries.hasNext()) {
        Map.Entry<Point, Particle> entry = entries.next();
        entry.getValue().Draw(canvas);
    }

但这导致: 在此处输入图片说明

如果有人怀疑它必须对它做点什么,这是在粒子类内部:

public class Particle {
    Bitmap bit;
    int alpha = 0;
    boolean appeared = false;
    boolean dissapiread = false;
    int time = 1;
    PointF position;
    Handler handler;
    int counter = 0;
    PointF newpose;
    float newsize=0;
    int timer2=0;
    public Particle(Bitmap b, PointF p, int time) {
        int rand=(randInt(-b.getWidth()/2, b.getWidth()));
        this.bit = Bitmap.createScaledBitmap(b, b.getWidth()+rand,b.getHeight()+rand,false);
        this.position = p;
        this.time = time;
        newpose= new PointF();
        newpose.x=p.x+randInt(-15000, 15000);
        newpose.y=p.y+randInt(-15000,15000);

    }

    public void Draw(Canvas c) {
        update();
        Paint paintAlpha = new Paint();
        paintAlpha.setAlpha(alpha);
        c.drawBitmap(bit, position.x, position.y, paintAlpha);
    }
    public static int randInt(int min, int max) {
        Random rand = new Random();
        int randomNum = rand.nextInt((max - min) + 1) + min;
        return randomNum;
    }
    private void update() {
        if(position.x<newpose.x){
            position.x+=0.10f;
        }
         if(position.x>newpose.x){
            position.x-=0.10f;
        }
        if(position.y<newpose.y){
            position.y+=0.10f;
        }
         if(position.y>newpose.y){
            position.y-=0.10f;
        }
         if(dissapiread==false){
         if(timer2==0){
             newsize+=0.10;
             try {
                 bit=Bitmap.createScaledBitmap(bit, bit.getWidth()-(int)newsize,bit.getHeight()-(int)newsize,false);
            } catch (Exception e) {
                // TODO: handle exception
            }
         timer2=5;
         }
         else
             timer2--;
         }

        if (appeared == false) {
            if (alpha <=240) {
                alpha =alpha+10;
            } 
            else {
                if(counter==0){

                counter=time;
                }
                if(counter==1){
                    appeared=true;
                }
                else
                    counter--;
            }
        } else {
            if (dissapiread == false) {
                if (alpha != 0) {
                    alpha=alpha-10;
                }
                else
                    dissapiread = true;
            }
        }
    }
}

请注意,我知道在当前代码中我不必使用哈希图,我只是想了解为什么它崩溃,因为它也发生在其他地方。

编辑:整个代码:

public class gameview extends SurfaceView {

    private GameLoopThread gameLoopThread;
    private SurfaceHolder holder;
    Bitmap partic;
    Particle pp;
    Map<Point, Particle> spawned = new HashMap<Point, Particle>();
public gameview(Context c) {
    super(c);
    partic=BitmapFactory.decodeResource(getResources(),
            R.drawable.particle_fire);
     pp=new Particle(partic, new PointF(0,0), 100);
    gameLoopThread = new GameLoopThread(this);
    this.requestFocus();
    this.setFocusableInTouchMode(true);
    holder = getHolder();
    holder.addCallback(new SurfaceHolder.Callback() {

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            boolean retry = true;
            gameLoopThread.setRunning(false);
            while (retry) {
                try {
                    gameLoopThread.join();
                    retry = false;
                } catch (InterruptedException e) {
                }
            }
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            gameLoopThread.setRunning(true);
            gameLoopThread.start();
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format,
                int width, int height) {
        }
    });
}
@Override
public void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    canvas.drawColor(Color.BLACK);
    pp.Draw(canvas);
        Iterator<Map.Entry<Point, Particle>> entries = spawned.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry<Point, Particle> entry = entries.next();
            entry.getValue().Draw(canvas);
        }
}
@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = (float) (event.getX());
    float y = (float) (event.getY());
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        spawned.put(new Point((int)x,(int)y), new Particle(partic, new PointF(x,y), 100));
        break;
    }
    return super.onTouchEvent(event);
}
private void newParticle(int x,int y){

    spawned.put(new Point(0,0), new Particle(partic, new PointF(x,y), 100));
}

}

Partice通过其Draw方法更新Partice 这会导致您在循环中遇到ConcurrentModificationException异常。

如果要避免此类异常,可以创建粒子集合的克隆,在该克隆上迭代和修改原始数据。 但是,对于您需要执行的操作,克隆可能非常麻烦。

对于克隆,我的意思是将HashMap的键复制到新的Set中并遍历该Set。 在循环内,您可以通过迭代的键访问HashMap值。 修改粒子应该没问题。 请注意,如果更新更改了对象的HashValue,则需要小心。

编辑:

正如@fge指出的那样,使用CuncurrentHashMap也可以解决该问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM