Reseting ArrayList iterator to first item?

K

Ken

Hi. I have an iterator to an ArrayList. I want to be able to reset
that iterator to the first item in the ArrayList. I see that one
approach is to use a ListIterator instead of an Iterator and loop
through hasPrevious/Previous until I'm at the first item. Is there a
better way to do this? I was surprised that ListIterator didn't just
have a "first" or "last" method.

Thanks for any info!

Ken
 
S

Stefan Waldmann

Ken said:
Hi. I have an iterator to an ArrayList. I want to be able to reset
that iterator to the first item in the ArrayList. I see that one
approach is to use a ListIterator instead of an Iterator and loop
through hasPrevious/Previous until I'm at the first item. Is there a
better way to do this? I was surprised that ListIterator didn't just
have a "first" or "last" method.

Thanks for any info!

Ken

Hello,

I see no possibility to reset an Iterator, unless creating a new one.
Iterators are intended to be used if you want to iterate over all
elements of a list once. Why don't you just iterate over your List
yourself, using an index variable?

List myList = new ArrayList();
// fill list ...

int i=0;
for(i=0; i<myList.size(); i++) {
Object myObj = myList.get(i);
// .. do whatever you intend to do
}

// reset your index
i = 0;

HTH,
Stefan
 
J

John C. Bollinger

Ken said:
Hi. I have an iterator to an ArrayList. I want to be able to reset
that iterator to the first item in the ArrayList. I see that one
approach is to use a ListIterator instead of an Iterator and loop
through hasPrevious/Previous until I'm at the first item. Is there a
better way to do this? I was surprised that ListIterator didn't just
have a "first" or "last" method.

The main alternative is to create a new Iterator over the same List.
That's only possible if you actually have the List, of course.
ListIterator doesn't have first() and last() methods because it is an
_iterator_: by definition, it works through the underlying List one
element at a time.


John Bollinger
(e-mail address removed)
 
R

Roedy Green

Hi. I have an iterator to an ArrayList. I want to be able to reset
that iterator to the first item in the ArrayList. I see that one
approach is to use a ListIterator instead of an Iterator and loop
through hasPrevious/Previous until I'm at the first item. Is there a
better way to do this? I was surprised that ListIterator didn't just
have a "first" or "last" method.

Iterators are one shot things. You usually just get a new one.
 
R

Roedy Green

ListIterator doesn't have first() and last() methods because it is an
_iterator_: by definition, it works through the underlying List one
element at a time.

Iterators could in theory iterate over collections where all the
elements don't exist at once. Each generation might be computed from
the previous one.
 
K

kk_oop

Hi.

The reason I don't want to get a new one is because I will be iterating
a particular list frequently, and I don't want to make a lot of objects
for garbage collection.

I think what I can do is get a ListIterator and when I want to "reset"
it, I can just loop through hasPrevious/previous until I'm back at the
beginning. Seems like it should work.

Thanks,

Ken
 
K

kk_oop

Stefan said:
I see no possibility to reset an Iterator, unless creating a new one.
Iterators are intended to be used if you want to iterate over all
elements of a list once. Why don't you just iterate over your List
yourself, using an index variable?

Because I want to to pass the iterator to other clients without them
caring that the collection is an ArrayList. That way if I want to
change it to a different kind of list at some point, the clients will
not be effected.
 
C

Carl Howells

kk_oop said:
Hi.

The reason I don't want to get a new one is because I will be iterating
a particular list frequently, and I don't want to make a lot of objects
for garbage collection.

I think what I can do is get a ListIterator and when I want to "reset"
it, I can just loop through hasPrevious/previous until I'm back at the
beginning. Seems like it should work.


Hahahaha....... Talk about premature "optimization".

Wow... Just wow. Your assumptions about performance are SO bad.

Why don't you actually TEST the performance of each approach? Make sure
to do it with several different sizes of backing List objects - with
each power of 10 up to 1,000,000, say.

I suppose that "resetting" the iterator *might* possibly be faster for
10 element List instances. I'm willing to bet that creating a new
iterator is faster for 100 and up. I might code up a benchmark for this
if you don't, and I have the time.

But you should give it a shot. The results will surprise you.
 
J

John C. Bollinger

kk_oop said:
The reason I don't want to get a new one is because I will be iterating
a particular list frequently, and I don't want to make a lot of objects
for garbage collection.

Then I hope you don't also plan to ever modify the list once you start
passing the Iterator around, as any modification will make the Iterator
useless.

You are in any case probably trying to solve a problem that doesn't
exist -- modern VMs make use of a variety of techniques to reduce the
cost of garbage collection. With the default "generational" garbage
collector in recent Sun VMs, GCing "young" objects is very cheap indeed.
I think what I can do is get a ListIterator and when I want to "reset"
it, I can just loop through hasPrevious/previous until I'm back at the
beginning. Seems like it should work.

That should work, in the sense that you can successfully return the
iterator to its initial state (or something close enough to it). It is
unlikely to be a performance win. (See Carl Howells' comments.)


John Bollinger
(e-mail address removed)
 
S

Scott Ellsworth

kk_oop said:
Hi.

The reason I don't want to get a new one is because I will be iterating
a particular list frequently, and I don't want to make a lot of objects
for garbage collection.

Do not be afraid of creating objects if they are not used for long, at
least as long as you are deploying to a recent JDK. The JDK is really
good about collecting those.

I do recommend changing the EMPTY_LIST implementation to return a
static instance of a custom iterator class.

Scott
 
K

kk_oop

Carl said:
Hahahaha....... Talk about premature "optimization".

Wow... Just wow. Your assumptions about performance are SO bad.

Why don't you actually TEST the performance of each approach? Make
sure to do it with several different sizes of backing List objects -
with each power of 10 up to 1,000,000, say.

I suppose that "resetting" the iterator *might* possibly be faster for
10 element List instances.

In the context I'm using it there will be between 7 to 10 items on the
list. The iterator would need to be reset about once every 4 seconds.
In addition to worrying about performance, we are also worried about
determinism since the garbage collector is beyond our control (I
know--if we are so worried about that, why aren't we using Java? Powers
above us all felt Java was the way to go. It's like the film producer
only financing the film if his mistress is cast as the lead. :) ).

Thanks,

Ken
 
K

kk_oop

John said:
Then I hope you don't also plan to ever modify the list once you start
passing the Iterator around, as any modification will make the
Iterator useless.

This is correct. No modifications for the life of the iterator.
You are in any case probably trying to solve a problem that doesn't
exist -- modern VMs make use of a variety of techniques to reduce the
cost of garbage collection. With the default "generational" garbage
collector in recent Sun VMs, GCing "young" objects is very cheap indeed.

It's more of a determinism vs. performance issue.
That should work, in the sense that you can successfully return the
iterator to its initial state (or something close enough to it). It
is unlikely to be a performance win. (See Carl Howells' comments.)

Well, we've got a small list here and determinism GC issues, so I'm
thinking this is the way to go.

Thanks,

Ken
 
C

Christophe Vanfleteren

kk_oop said:
In the context I'm using it there will be between 7 to 10 items on the
list. The iterator would need to be reset about once every 4 seconds.
In addition to worrying about performance, we are also worried about
determinism since the garbage collector is beyond our control (I
know--if we are so worried about that, why aren't we using Java? Powers
above us all felt Java was the way to go. It's like the film producer
only financing the film if his mistress is cast as the lead. :) ).

Seriously, that will only be a problem if you intend to run this program on
something like a 486 with 16MB RAM.

As someone said before, don't start with these silly, premature
optimizations. Concentrate on finishing your program first, and then you
can improve performance, if it is deemded necessary.
 
M

Michael Borgwardt

You're kidding, right? If it werre 4 million times every second, then
it might be a problem. MIGHT, on a modern machine.

Stuff that is egligible for garbage collection will be automatically
irrelevant to the program (unless finalizers are used, which is why
they shouldn't be), so there is nothing to worry about.
Seriously, that will only be a problem if you intend to run this program on
something like a 486 with 16MB RAM.

Even a 386 at 20 MHz could create many thousands of new Interator objects
per second.
 
S

Scott Ellsworth

kk_oop said:
Could you elaborate?

Remember that the standard implementation is almost always good enough,
given modern GC and modern JITCs. If your code uses a LOT of empty
lists, though, you can have a problem.

One program I worked with had hundreds of thousands of empty lists that
got iterated through. A first step towards fixing the performance
problems was a fix for that. A later step dropped the number of calls
dramatically, which is typical. Fix the algorithm, not the detail code,
for real performance gain. That said, a detail fix had a lot of
benefits.

The immutable EMPTY_LIST, in Collections.java, has the code:

private static class EmptyList extends AbstractList
implements RandomAccess, Serializable
{
private static final long serialVersionUID = 8842843931221139166L;
public int size() {return 0;}
public boolean contains(Object obj) {return false;}
public Object get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}
private Object readResolve() {
return EMPTY_LIST;
}
}

We see, therefore, that whenever iterator() is called, you get the
standard one in AbstractList. Thus, there are several needless function
calls. If you know that you are going to have a LOT of these, you might
do better with an implementation like:

private static class MyEmptyList extends AbstractList
implements RandomAccess, Serializable
{
private static final long serialVersionUID = 8842843931221139166L;
public int size() {return 0;}
public boolean contains(Object obj) {return false;}
public Object get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}
private Object readResolve() {
return MY_EMPTY_LIST;
}
public Iterator iterator() {
return new Iterator() {
public boolean hasNext() {
return false;
}
public Object next() {
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}

This does create a new iterator for every call, though, so it is not
ideal if you try to iterate through a lot of empty collections. The
following caches the iterator:

private static class MyEmptyList extends AbstractList
implements RandomAccess, Serializable
{
private static final long serialVersionUID = 8842843931221139166L;
public int size() {return 0;}
public boolean contains(Object obj) {return false;}
public Object get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}
private Object readResolve() {
return MY_EMPTY_LIST;
}
private static empty_iterator;
public Iterator iterator() {
if (empty_iterator==null) empty_iterator=new Iterator() {
public boolean hasNext() {
return false;
}
public Object next() {
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
return empty_iterator;
}
}

Again, do not do this until your profiler indicates it is a good idea.

Scott
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,142
Latest member
DewittMill
Top