tags:

views:

283

answers:

4

How to remove specific element on List?

...
java.util.List<Polygon> triangles = new LinkedList<Polygon>();
Point startDrag, endDrag, midPoint;
Polygon triangle;

....
int[] xs = { startDrag.x, endDrag.x, midPoint.x };
int[] ys = { startDrag.y, startDrag.y, midPoint.y };    

triangles.add( new Polygon(xs, ys,3));   
....

public void mouseClicked(MouseEvent e) {
...
   startDrag = new Point(e.getX(), e.getY());
   for (Polygon p:triangles){
    if (p.contains(startDrag)) //Polygon has a 'contains(Point)' method
           remove (p.contains(startDrag));
   }
....
+3  A: 

You will not be able to remove the object from the triangles list if you are currently iterating over it. If you try to do so, you will trigger a ConcurrentModificationException. Instead, what you should do is make a copy of the list and iterate over that, and when you get a hit, remove the item from the original:

public void mouseClicked(MouseEvent e) {
...
   Polygon[] triArray = triangles.toArray(new Polygon[triangles.size()]);
   startDrag = new Point(e.getX(), e.getY());
   for (Polygon p:triArray){
    if (p.contains(startDrag)) //Polygon has a 'contains(Point)' method
           triangles.remove (p);
   }
....
akf
Thanks for the code akf :-)
Jessy
+4  A: 

To remove by object, such as removing a specific triangle from a triangle list, use List::remove(Object)

For the above purposes, you might want to use List::listIterator(), though. Something like:

ListIterator<Polygon> it = triangles.listIterator();
while (it.hasNext()) {
  if (it.next().contains(startDrag)) {
    it.remove();
    break;
  }
}
Gunslinger47
Just `List`/`Collection.iterator` should be sufficient.
Tom Hawtin - tackline
A: 

For some reason this code works without concurrent modification:

    ArrayList<Polygon> list = new ArrayList<Polygon>();

 list.add(new Polygon(new int[] { 1, 3, 1 }, new int[] { 2, 3, 1 }, 3));
 list.add(new Polygon(new int[] { 2, 3, 1 }, new int[] { 3, 4, 1 }, 3));
 list.add(new Polygon(new int[] { 4, 5, 1 }, new int[] { 5, 6, 1 }, 3));

 for (Polygon i : list) {
  if (i.contains(new Point(2, 3))) {
   System.out.println("Removing " + i);
   list.remove(i);
  }
 }

 for (Polygon i : list) {
  System.out.println(i);
 }

It removes first polygon.

tulskiy
Actually, your code does not remove the first item, it removed the second. If you put in a couple more debug statements, you will see. The `checkForConcurrency()` method that would normally throw the CME will then not be called - because the `hasNext()` method in the iterator will return false because the cursor will equal the size of the iterator.
akf
If you rearrange the order of your list inserts, you will trigger the exception.
akf
Did not test enough, sorry.
tulskiy
I still believe that creating an array from list is too much. It would be more efficient to use iterators or create a list of items to delete and then call removeAll()
tulskiy
A: 

This is a nasty, I dug it - it's the system thread from the Mouse Clicked being identified as not the creator of the java.util.Thingamabob ( a new data structure to be released tomorrow )

Despite documentation, in alignment with common sense, what the thing does actually is see that the thread from MouseClicked is not the Thread that created

java.util.List<Polygon> triangles

using something on the order of Thread ID or such as naming of threads go and then throws from deep within the JVM an exception ( sets the exception flag on the C side ) then returns leaving you with no functioning exception.getMessage() .....

You can implement copy semantics and the original version will work, does some bit-twisting on your brain but it works.

Nicholas Jordan
What are you talking about?
Tom Hawtin - tackline
it's pretty deep, I have not had good reliability trying to answer these but what I was trying to say was to note for the reader that "Concurrent Modification Exception" was not implemented as I would think - rather than detecting two threads of which one does a remove() what had been done was to set the exception flag in the jvm solely on the basis that the thread attempting a remove() was not the thread that had created the java.uti.Collection. A button working from a system event thread could not modify even though synchronization semantics were observed.
Nicholas Jordan