Error while removing Arraylist item

Asked

Viewed 384 times

1

I’m "playing" with the canvas (android) and I’m having trouble removing element from an Arraylist.

The app works like this: The user clicks on the screen, a ball appears that goes up but I want to remove only the balls that exceeded the limit y <= -50. When I remove it generates this error:

09-08 23:28:12.617: E/AndroidRuntime(6719):  FATAL EXCEPTION: Thread-2330
09-08 23:28:12.617: E/AndroidRuntime(6719):  java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
09-08 23:28:12.617: E/AndroidRuntime(6719):  at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
09-08 23:28:12.617: E/AndroidRuntime(6719):  at java.util.ArrayList.get(ArrayList.java:304)
09-08 23:28:12.617: E/AndroidRuntime(6719):  at com.dotjogoqualquer.JogoView.update(JogoView.java:50)
09-08 23:28:12.617: E/AndroidRuntime(6719):  at com.dotjogoqualquer.JogoView.run(JogoView.java:40)
09-08 23:28:12.617: E/AndroidRuntime(6719):  at java.lang.Thread.run(Thread.java:856)

Code

public void update() {
                if (obj.size() >= 1){
                        for(int x = 0; x < obj.size(); x++) {
                                obj.get(x).y -= 15;
                                if (obj.get(x).y < -50) {
                                        obj.remove(x); //Erro ocorre aqui
                                }
                        }
                }
                postInvalidate();
        }

Links to the complete code
http://pastebin.com/hDz3nyzk (Line 48)

  • What if you try to use the object and not the index to perform the removal? , as in this example

  • like this oh... public void update() { if (obj.size() >= 1){ for(int x = 0; x < obj.size(); x++) { obj.get(x). y -= 15; if (obj.get(x).y < -50) { obj.remove(obj.get(x)); // <<======================== HERE } } } postInvalidate(); }

  • tried that which would be most correct (I think) for(objetos _x : obj) {&#xA; _x.y -= 15;&#xA; if (_x.y < -50) {&#xA; obj.remove(_x);&#xA; }&#xA; } resulted in this error http://pastebin.com/QCLP0ipJ

  • 2

    viche, now you are removing the item, but at the same time have people adding, who knows if you use synchronizedList

2 answers

2


The error happens because you are removing the items from the list from within a for, it happens because when the for was "mounted" by the VM the list had a size X, you removed some items, so when calling list.get(x) and x is greater than the number of items in the list an exception will be launched.

In a FOR its first two parts (the variable declaration and the stop condition) are called only once.

Suppose your list has 10 items, so the call to obj.size() will return 10, as the stop condition is x < 10 the loop will run regardless of whether items have been removed or added to the list. Let’s imagine that the list has 10 items:

 for(int x = 0; x < obj.size(); x++) { // Aqui foi definido que o loop vai até X == 9

      // Se um item for removido, vai dar erro AQUI 
      // na ultima iteração do loop, pois o tamanho da lista será 8 e x será 9
      obj.get(x).y -= 15; 

      if (obj.get(x).y < -50) { //Se nenhum item for removido não vai dar erro

          obj.remove(x); 
      }
 }

In addition there are more elegant ways to do the same thing, if you are using Java 7 you can use the utility classes of Guava to apply your logic. Using Guava would look like this:

     List<TipoDeDados> listaTransformada = Lists.transform(lista, new Function<TipoDeDados, TipoDeDados>() {

        @Override
        public TipoDeDados apply(TipoDeDados input) {
            input.y -= 15;
            return input;
        }
    });

    Iterables.removeIf(listaTransformada, new Predicate<TipoDeDados>() {

        @Override
        public boolean apply(TipoDeDados input) {
            return input.y < -50;
        }
    });

The good thing about using the Function and Predicate classes is that you can give a descriptive name to the implementations which makes it easier to understand the algorithm.

Already if you are using version 8 of Java, it is even simpler, just use the methods of the List interface itself, getting so:

    lista.forEach( tipoDeDado -> tipoDeDado.y -= 15);

    lista.removeIf( tipoDeDado -> tipoDeDado.y < -50 );

0

Is there more than one thread messing with the list at the same time? Try to surround every snippet of code that handles this list with

Synchronized (obj) { ... }

The whole body of the question method must be protected in this way. By the way, check if size() >= 1 is unnecessary because the loop does nothing if the list has no element.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.