Removing object from arraylist when pointed to by iterator

Discussion in 'Java' started by nooneinparticular314159@yahoo.com, Aug 24, 2008.

  1. Guest

    I have an arraylist of objects of a certain type. I use an iterator
    on that arraylist to get the next instance of the object, using the
    iterator.next() method. But if I succeed in performing an operation
    on the object, I want to remove the object from my arraylist. The
    question is how I remove it without calling .next() again, since that
    will remove the next one, not the current one? ie. If I am currently
    working on the object at position 4 in the arraylist (through the
    iterator), I want to remove the object at position 4. But I don't
    know what position the object is in because I got it through the
    iterator.

    Thanks!
     
    , Aug 24, 2008
    #1
    1. Advertising

  2. Arne Vajhøj Guest

    wrote:
    > I have an arraylist of objects of a certain type. I use an iterator
    > on that arraylist to get the next instance of the object, using the
    > iterator.next() method. But if I succeed in performing an operation
    > on the object, I want to remove the object from my arraylist. The
    > question is how I remove it without calling .next() again, since that
    > will remove the next one, not the current one? ie. If I am currently
    > working on the object at position 4 in the arraylist (through the
    > iterator), I want to remove the object at position 4. But I don't
    > know what position the object is in because I got it through the
    > iterator.


    Save a ref to what next() returns.

    And I am pretty sure that the ArrayList iterator does not like
    you calling remove while iterating.

    Arne
     
    Arne Vajhøj, Aug 24, 2008
    #2
    1. Advertising

  3. On Aug 24, 3:00 am, ""
    <> wrote:
    > I have an arraylist of objects of a certain type.  I use an iterator
    > on that arraylist to get the next instance of the object, using the
    > iterator.next() method.  But if I succeed in performing an operation
    > on the object, I want to remove the object from my arraylist.  The
    > question is how I remove it without calling .next() again, since that
    > will remove the next one, not the current one?  ie.  If I am currently
    > working on the object at position 4 in the arraylist (through the
    > iterator), I want to remove the object at position 4.  But I don't
    > know what position the object is in because I got it through the
    > iterator.


    I would say you're caught in the iterator "routine" so many fall prey
    to... you should not be using an iterator when working with an
    ArrayList ! You should be iterating the "old fashioned" way ... using
    direct get(int) .. these don't entertain the concept of
    ConcurrentModificationException. It's faster too.
     
    softwarepearls_com, Aug 24, 2008
    #3
  4. wrote:
    > I have an arraylist of objects of a certain type. I use an iterator
    > on that arraylist to get the next instance of the object, using the
    > iterator.next() method. But if I succeed in performing an operation
    > on the object, I want to remove the object from my arraylist. The
    > question is how I remove it without calling .next() again, since
    > that
    > will remove the next one, not the current one? ie. If I am
    > currently
    > working on the object at position 4 in the arraylist (through the
    > iterator), I want to remove the object at position 4. But I don't
    > know what position the object is in because I got it through the
    > iterator.



    If you call remove() on the iterator, you'll remove the last one
    fetched. That is, code like

    ArrayList<MyType> list;
    for (Iterator<MyType> iter = list.iterator(); iter.hasNext(); )
    {
    MyType obj = list.next();
    if (shouldBeRemoved(obj))
    iter.remove();
    }

    does what you want.
     
    Mike Schilling, Aug 24, 2008
    #4
  5. softwarepearls_com <> wrote in news:f472d0ee-f85b-
    :

    > On Aug 24, 3:00 am, ""
    ><> wrote:
    >> I have an arraylist of objects of a certain type.  I use an iterator
    >> on that arraylist to get the next instance of the object, using the
    >> iterator.next() method.  But if I succeed in performing an operation
    >> on the object, I want to remove the object from my arraylist.  The
    >> question is how I remove it without calling .next() again, since that
    >> will remove the next one, not the current one?  ie.  If I am currentl

    > y
    >> working on the object at position 4 in the arraylist (through the
    >> iterator), I want to remove the object at position 4.  But I don't
    >> know what position the object is in because I got it through the
    >> iterator.

    >
    > I would say you're caught in the iterator "routine" so many fall prey
    > to... you should not be using an iterator when working with an
    > ArrayList ! You should be iterating the "old fashioned" way ... using
    > direct get(int) .. these don't entertain the concept of
    > ConcurrentModificationException. It's faster too.


    If one wants to iterate thru the ArrayList, and remove items here and
    there, I'd say an Iterator is much simpler and safer to use.

    Iterating with an index may cause undesired results, as shown by the
    following example.

    package itertest;

    import java.util.List;
    import java.util.ArrayList;
    import java.util.Iterator;

    public class Main
    {
    public static void main(String[] args)
    {
    final int SIZE=1000;
    List list = new ArrayList(SIZE) ;

    for (int i=0; i < SIZE; i++)
    {
    list.add(Integer.toString(i));
    }

    for (int i=0; i < list.size(); i++)
    {
    String s = (String) list.get(i) ;
    System.out.println("list.get(" + i + ") (list.size=" +
    list.size() + ") = " + s) ;
    list.remove(i) ;
    }

    list = new ArrayList(SIZE) ;

    for (int i=0; i < SIZE; i++)
    {
    list.add(Integer.toString(i));
    }

    for (Iterator i=list.iterator(); i.hasNext(); )
    {
    String s = (String) i.next() ;
    System.out.println("i.next() = " + s) ;
    i.remove();
    }
    }
    }


    The list will never get iterated thru by using get() ! The algorighm
    using that requires something more, which makes it more complicated.
     
    Donkey Hottie, Aug 24, 2008
    #5
  6. Daniel Pitts Guest

    wrote:
    > I have an arraylist of objects of a certain type. I use an iterator
    > on that arraylist to get the next instance of the object, using the
    > iterator.next() method. But if I succeed in performing an operation
    > on the object, I want to remove the object from my arraylist. The
    > question is how I remove it without calling .next() again, since that
    > will remove the next one, not the current one? ie. If I am currently
    > working on the object at position 4 in the arraylist (through the
    > iterator), I want to remove the object at position 4. But I don't
    > know what position the object is in because I got it through the
    > iterator.
    >
    > Thanks!

    it.remove(); will remove the object that was last returned by it.next()

    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
     
    Daniel Pitts, Aug 24, 2008
    #6
  7. Daniel Pitts Guest

    softwarepearls_com wrote:
    > On Aug 24, 3:00 am, ""
    > <> wrote:
    >> I have an arraylist of objects of a certain type. I use an iterator
    >> on that arraylist to get the next instance of the object, using the
    >> iterator.next() method. But if I succeed in performing an operation
    >> on the object, I want to remove the object from my arraylist. The
    >> question is how I remove it without calling .next() again, since that
    >> will remove the next one, not the current one? ie. If I am currently
    >> working on the object at position 4 in the arraylist (through the
    >> iterator), I want to remove the object at position 4. But I don't
    >> know what position the object is in because I got it through the
    >> iterator.

    >
    > I would say you're caught in the iterator "routine" so many fall prey
    > to... you should not be using an iterator when working with an
    > ArrayList ! You should be iterating the "old fashioned" way ... using
    > direct get(int) .. these don't entertain the concept of
    > ConcurrentModificationException. It's faster too.

    Lies!

    You don't see the concurrent modification errors, but they still can
    cause bugs in your code!
    Also, It isn't necessarily faster. I would assume its "about the same"
    for the average program, but the benefits of using an iterator far
    outweigh the cost for the average program. Fewer bugs, bugs caught
    sooner, etc...
    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
     
    Daniel Pitts, Aug 24, 2008
    #7
  8. Daniel Pitts wrote:
    > softwarepearls_com wrote:
    >> On Aug 24, 3:00 am, ""
    >> <> wrote:
    >>> I have an arraylist of objects of a certain type. I use an
    >>> iterator
    >>> on that arraylist to get the next instance of the object, using
    >>> the
    >>> iterator.next() method. But if I succeed in performing an
    >>> operation
    >>> on the object, I want to remove the object from my arraylist. The
    >>> question is how I remove it without calling .next() again, since
    >>> that will remove the next one, not the current one? ie. If I am
    >>> currently working on the object at position 4 in the arraylist
    >>> (through the iterator), I want to remove the object at position 4.
    >>> But I don't know what position the object is in because I got it
    >>> through the iterator.

    >>
    >> I would say you're caught in the iterator "routine" so many fall
    >> prey
    >> to... you should not be using an iterator when working with an
    >> ArrayList ! You should be iterating the "old fashioned" way ...
    >> using
    >> direct get(int) .. these don't entertain the concept of
    >> ConcurrentModificationException. It's faster too.

    > Lies!
    >
    > You don't see the concurrent modification errors, but they still can
    > cause bugs in your code!
    > Also, It isn't necessarily faster. I would assume its "about the
    > same" for the average program, but the benefits of using an iterator
    > far outweigh the cost for the average program. Fewer bugs, bugs
    > caught sooner, etc...


    And it's easier to get right. Iterator.remove() does what the OP
    wants. The equivalent with integer indices is:

    for (int i = 0; i < list.length(); i++)
    {
    if (shouldRemove(list.get(i))
    {
    list.remove(i);
    i--; // Needed to avoid skipping a list member.
    // Or is it?
    }
    }

    And, when iterating the other way:

    for (int i = list.length()-1; i >= 0; i--)
    {
    if (shouldRemove(list.get(i))
    {
    list.remove(i);
    i++; // Needed to avoid skipping a list member.
    // Or is it?
    }
    }

    The answers are "yes" and "no" respectively, but why take the chance
    of getting it wrong?
     
    Mike Schilling, Aug 24, 2008
    #8
  9. jolz Guest

    Instead of calling iterator.remove() for every object you remove you can:
    - remember all object that you want to keep in a temporary list
    - after loop is finished clear original list and insert to it content of
    the temporary list (or switch references if it isn't used anywherere
    else in the code)
    Above makes no sense if you have 5 objects in the list, but with many
    objects often removed from an ArrayList you will notice that calling
    iterator.remove() slows down your application.
    Or you can use LinkedList instead of ArrayList if you allways use
    iterators - obiously code with a single call iterator.remove(); is
    simpler and removing from LinkedList is way faster thar removing from
    ArrayList.
     
    jolz, Aug 24, 2008
    #9
  10. Tom Anderson Guest

    On Sun, 24 Aug 2008, softwarepearls_com wrote:

    > On Aug 24, 3:00 am, ""
    > <> wrote:
    >
    >> I have an arraylist of objects of a certain type.  I use an iterator on
    >> that arraylist to get the next instance of the object, using the
    >> iterator.next() method.  But if I succeed in performing an operation on
    >> the object, I want to remove the object from my arraylist.  The
    >> question is how I remove it without calling .next() again, since that
    >> will remove the next one, not the current one?  ie.  If I am currently
    >> working on the object at position 4 in the arraylist (through the
    >> iterator), I want to remove the object at position 4.  But I don't know
    >> what position the object is in because I got it through the iterator.

    >
    > I would say you're caught in the iterator "routine" so many fall prey
    > to... you should not be using an iterator when working with an ArrayList
    > ! You should be iterating the "old fashioned" way ... using direct
    > get(int) .. these don't entertain the concept of
    > ConcurrentModificationException. It's faster too.


    No. I mean, this is just really terrible advice. Please don't ever give
    anyone advice again. You're really not helping.

    tom

    --
    In Milan, [traffic lights] are instructions, in Rome suggestions, and
    in Naples Christmas decorations. -- James Dowden
     
    Tom Anderson, Aug 24, 2008
    #10
  11. Paul Tomblin Guest

    In a previous article, Tom Anderson <> said:
    >On Sun, 24 Aug 2008, softwarepearls_com wrote:
    >> ! You should be iterating the "old fashioned" way ... using direct
    >> get(int) .. these don't entertain the concept of
    >> ConcurrentModificationException. It's faster too.

    >
    >No. I mean, this is just really terrible advice. Please don't ever give
    >anyone advice again. You're really not helping.


    What he said.

    There is no way in hell that using "get" is faster than an iterator. And
    maybe you won't see a ConcurrentModificationException, but that's because
    doing it that way won't notice the bugs you've introduced by concurrent
    modifications.

    --
    Paul Tomblin <> http://blog.xcski.com/
    I trust the cut & paste under Win2k's telnet about as far as I can
    comfortably spit a rat.
    -- John Burnham
     
    Paul Tomblin, Aug 24, 2008
    #11
  12. (Paul Tomblin) writes:

    [About ArrayList]
    > There is no way in hell that using "get" is faster than an iterator.


    Since ArrayList inherits its iterator from AbstractList, which says:
    ---
    * Unlike the other abstract collection implementations, the programmer does
    * <i>not</i> have to provide an iterator implementation; the iterator and
    * list iterator are implemented by this class, on top the "random access"
    * methods: <tt>get(int index)</tt>, <tt>set(int index, Object element)</tt>,
    * <tt>set(int index, Object element)</tt>, <tt>add(int index, Object
    * element)</tt> and <tt>remove(int index)</tt>.<p>
    ---
    it would indeed be odd if the iterator is slower. It can, at best, be
    as fast as using "get", and it has its own overhead too (e.g., its
    index is stored in a field on the iterator, where a loop using "get"
    could use a local variable).
    Whether the overhead is significant, or it is optimized away by
    the runtime system, only profiling can say.

    > And maybe you won't see a ConcurrentModificationException, but
    > that's because doing it that way won't notice the bugs you've
    > introduced by concurrent modifications.


    That is correct, except in the case where you know, and I mean
    *absolutely* know, that the list is only *ever* used in a single
    thread.


    /L
    --
    Lasse Reichstein Nielsen
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Aug 25, 2008
    #12
  13. Daniel Pitts Guest

    Lasse Reichstein Nielsen wrote:
    >> And maybe you won't see a ConcurrentModificationException, but
    >> that's because doing it that way won't notice the bugs you've
    >> introduced by concurrent modifications.

    >
    > That is correct, except in the case where you know, and I mean
    > *absolutely* know, that the list is only *ever* used in a single
    > thread.

    Concurrent modification bugs do not require multiple threads to appear.
    As a matter of fact, I've run into them most often in programs where
    only one thread has access to the collection in question. Algorithms
    like the following can lead to the bug:

    1. Go through all SimulationObjects
    2. execute doSomething on each object.

    where the some SimulationObject instance have a doSomething that can
    affect the list of all simulation objects. Such as a robot firing a
    missile (addition), or a missile exploding and killing a robot
    (removal). In that case, I might never have noticed the bug if I was
    using get. As it turns out, the "best" way around that bug in my code
    was to create a two lists "toBeRemoved" and "toBeAdded", and handle that
    after the main loop.

    So, the point remains, use Iterator, and if you get CME don't assume its
    a synchronization/threading issue (although it might me).


    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
     
    Daniel Pitts, Aug 25, 2008
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Saravanan Rathinavelu

    Iterate through ArrayList using an another ArrayList

    Saravanan Rathinavelu, Aug 16, 2003, in forum: ASP .Net
    Replies:
    3
    Views:
    2,794
    Natty Gur
    Aug 19, 2003
  2. Kaidi
    Replies:
    4
    Views:
    2,486
    Kaidi
    Jan 3, 2004
  3. Alien
    Replies:
    6
    Views:
    505
  4. Arkaitz Jimenez

    Modify pointed object method behaviour

    Arkaitz Jimenez, Jun 10, 2009, in forum: C++
    Replies:
    1
    Views:
    246
    James Kanze
    Jun 11, 2009
  5. nicollete

    Store Address of object pointed to

    nicollete, Nov 10, 2009, in forum: C Programming
    Replies:
    6
    Views:
    489
    Tarique.
    Nov 11, 2009
Loading...

Share This Page