How to Use an Iterator

Ways to iterate over a list in Java

The three forms of looping are nearly identical. The enhanced for loop:

for (E element : list) {
. . .
}

is, according to the Java Language Specification, identical in effect to the explicit use of an iterator with a traditional for loop. In the third case, you can only modify the list contents by removing the current element and, then, only if you do it through the remove method of the iterator itself. With index-based iteration, you are free to modify the list in any way. However, adding or removing elements that come before the current index risks having your loop skipping elements or processing the same element multiple times; you need to adjust the loop index properly when you make such changes.

In all cases, element is a reference to the actual list element. None of the iteration methods makes a copy of anything in the list. Changes to the internal state of element will always be seen in the internal state of the corresponding element on the list.

Essentially, there are only two ways to iterate over a list: by using an index or by using an iterator. The enhanced for loop is just a syntactic shortcut introduced in Java 5 to avoid the tedium of explicitly defining an iterator. For both styles, you can come up with essentially trivial variations using for, while or do while blocks, but they all boil down to the same thing (or, rather, two things).

EDIT: As @iX3 points out in a comment, you can use a ListIterator to set the current element of a list as you are iterating. You would need to use List#listIterator() instead of List#iterator() to initialize the loop variable (which, obviously, would have to be declared a ListIterator rather than an Iterator).

Should I use an Iterator or a forloop to iterate?

A foreach is equivalent to an iterator--it's syntactic sugar for the same thing. So you should always choose foreach over iterator whenever you can, simply because it's convenient and results in more concise code.

I've written about this in another answer: https://stackoverflow.com/questions/22110482/uses-and-syntax-for-for-each-loop-in-java/22110517#22110517

As stated by @RonnyShapiro, there are situations where you need to use an iterator, but in many cases a foreach should suffice. Note that a foreach is not a normal for loop. The normal for loop is needed when access to the index is required. Although you could manually create a separate index int-variable with foreach it is not ideal, from a variable-scope point of view.

Here's some more information: Which is more efficient, a for-each loop, or an iterator?

When accessing collections, a foreach is significantly faster than the basic for loop's array access. When accessing arrays, however--at least with primitive and wrapper-arrays--access via indexes is way faster. See below.


Indexes are 23-40 percent faster than iterators when accessing int or Integer arrays. Here is the output from the below testing class, which sums the numbers in a 100-element primitive-int array (A is iterator, B is index):

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 358,597,622 nanoseconds
Test B: 269,167,681 nanoseconds
B faster by 89,429,941 nanoseconds (24.438799231635727% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 377,461,823 nanoseconds
Test B: 278,694,271 nanoseconds
B faster by 98,767,552 nanoseconds (25.666236154695838% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 288,953,495 nanoseconds
Test B: 207,050,523 nanoseconds
B faster by 81,902,972 nanoseconds (27.844689860906513% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,373,765 nanoseconds
Test B: 283,813,875 nanoseconds
B faster by 91,559,890 nanoseconds (23.891659337194227% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,790,818 nanoseconds
Test B: 220,770,915 nanoseconds
B faster by 155,019,903 nanoseconds (40.75164734599769% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 326,373,762 nanoseconds
Test B: 202,555,566 nanoseconds
B faster by 123,818,196 nanoseconds (37.437545972215744% faster)

The full testing class:

   import  java.text.NumberFormat;
import java.util.Locale;
/**
<P>{@code java TimeIteratorVsIndexIntArray 1000000}</P>

@see <CODE><A HREF="https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java">https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java</A></CODE>
**/
public class TimeIteratorVsIndexIntArray {
public static final NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
public static final void main(String[] tryCount_inParamIdx0) {
int testCount;
//Get try-count from command-line parameter
try {
testCount = Integer.parseInt(tryCount_inParamIdx0[0]);
} catch(ArrayIndexOutOfBoundsException | NumberFormatException x) {
throw new IllegalArgumentException("Missing or invalid command line parameter: The number of testCount for each test. " + x);
}

//Test proper...START
int[] intArray = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100};

long lStart = System.nanoTime();
for(int i = 0; i < testCount; i++) {
testIterator(intArray);
}
long lADuration = outputGetNanoDuration("A", lStart);

lStart = System.nanoTime();
for(int i = 0; i < testCount; i++) {
testFor(intArray);
}
long lBDuration = outputGetNanoDuration("B", lStart);

outputGetABTestNanoDifference(lADuration, lBDuration, "A", "B");
}
private static final void testIterator(int[] int_array) {
int total = 0;
for(int i = 0; i < int_array.length; i++) {
total += int_array[i];
}
}
private static final void testFor(int[] int_array) {
int total = 0;
for(int i : int_array) {
total += i;
}
}
//Test proper...END

//Timer testing utilities...START
public static final long outputGetNanoDuration(String s_testName, long l_nanoStart) {
long lDuration = System.nanoTime() - l_nanoStart;
System.out.println("Test " + s_testName + ": " + nf.format(lDuration) + " nanoseconds");
return lDuration;
}

public static final long outputGetABTestNanoDifference(long l_aDuration, long l_bDuration, String s_aTestName, String s_bTestName) {
long lDiff = -1;
double dPct = -1.0;
String sFaster = null;
if(l_aDuration > l_bDuration) {
lDiff = l_aDuration - l_bDuration;
dPct = 100.00 - (l_bDuration * 100.0 / l_aDuration + 0.5);
sFaster = "B";
} else {
lDiff = l_bDuration - l_aDuration;
dPct = 100.00 - (l_aDuration * 100.0 / l_bDuration + 0.5);
sFaster = "A";
}
System.out.println(sFaster + " faster by " + nf.format(lDiff) + " nanoseconds (" + dPct + "% faster)");
return lDiff;
}
//Timer testing utilities...END
}

I also ran this for an Integer array, and indexes are still the clear winner, but only between 18 and 25 percent faster.

For a List of Integers, however, iterators are faster. Just change the int-array in the above code to

List<Integer> intList = Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100});

and make the necssary changes to the test-function (int[] to List<Integer>, length to size(), etc)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,429,929,976 nanoseconds
Test B: 5,262,782,488 nanoseconds
A faster by 1,832,852,512 nanoseconds (34.326681820485675% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,907,391,427 nanoseconds
Test B: 3,957,718,459 nanoseconds
A faster by 1,050,327,032 nanoseconds (26.038700083921256% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,566,004,688 nanoseconds
Test B: 4,221,746,521 nanoseconds
A faster by 1,655,741,833 nanoseconds (38.71935684115413% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,770,945,276 nanoseconds
Test B: 3,829,077,158 nanoseconds
A faster by 1,058,131,882 nanoseconds (27.134122749113843% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,467,474,055 nanoseconds
Test B: 5,183,149,104 nanoseconds
A faster by 1,715,675,049 nanoseconds (32.60101667104192% faster)

[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,439,983,933 nanoseconds
Test B: 3,509,530,312 nanoseconds
A faster by 69,546,379 nanoseconds (1.4816434912159906% faster)

[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,451,101,466 nanoseconds
Test B: 5,057,979,210 nanoseconds
A faster by 1,606,877,744 nanoseconds (31.269164666060377% faster)

In one test they're almost equivalent, but still, iterator wins.

How to use iterator to retrieve objects from two classes in Java

first of all, ArrayList with object is bad practice, prefer to use this

List<Market> a1 = new ArrayList<>();
List<RetailShop> a2 = new ArrayList<>();

//Adding Market
al.add(m1);
al.add(m2);
al.add(m3);
al.add(m4);
al.add(m5);
//Adding RetailShop

a2.add(rt1);
a2.add(rt2);
a3.add(rt3);

for(Market mt:a1){
System.out.println(mt.billamount);
System.out.println(mt.customer);
System.out.println(mt.invoiceno);
}
for(RetailShop rts:a2){
System.out.println(rts.custName);
}

If you want to use one list, then you indeed need to cast, but you should check the cast like so:

while(itr.hasNext())
{
Object o = itr.next();
if(o instanceof Market){
Market mt = (Market) o;
System.out.println(mt.billamount);
System.out.println(mt.customer);
System.out.println(mt.invoiceno);
}else if(o instanceof RetailShop){
RetailShop rts=(RetailShop) o;
System.out.println(rts.custName);
}

}

What this does is it checks the class of each element in the list. If it's a market, it'll cast the object to a market and do the relevant code for it. And the came for the retailshop.

how to use iterator in while loop statement in python

In Python >= 3.8, you can do the following, using assignment expressions:

i = iter(range(10))
while (x := next(i, None)) is not None and x < 5:
print(x)

In Python < 3.8 you can use itertools.takewhile:

from itertools import takewhile

i = iter(range(10))
for x in takewhile({some logic}, i):
# do stuff

"Some logic" here would be a 1-arg callable receciving whatever next(i) yields:

for x in takewhile(lambda e: 5 > e, i):
print(x)
0
1
2
3
4

Using an iterator with an enhanced for loop in Java?

You need to loop (and remove) using the iterator itself.

for (Sprite s : sprites) {

should be changed to,

Iterator<Sprite> it = sprites.iterator();
while (it.hasNext()) {
Sprite s = it.next();

And then your if condition will be,

if (s.shouldRemove())
it.remove();

Do we ever need to use Iterators on ArrayList?

A big use case of iterators with ArrayLists is when you want to remove elements while iterating. You have only three safe solutions :

  • use an iterator and its remove method
  • copy the elements you want to keep in another list
  • jungle with indexes

Assuming you don't add while iterating, using the iterator is a mean to avoid the ConcurrentModificationException.

The readability argument is subjective. Personally I don't find a cleanly declared iterator less readable. And it doesn't really matter as the iterator is the safe way to iterate and remove at the same time.

How to use an iterator to find a specific title in an object that is part of an arraylist

For iterating through the Arraylist you can either make use of the for-each loop or iterate using Iterators. You are trying to use both of them together and I dont see any advantage in that. You want to do something like this :

Option 1 :

  Iterator<MediaItem> it = items.iterator();
while(it.hasNext())
{
MediaItem mi = it.next();
if(mi.getTitle().equals(title))
{
mi.setLoanedTo(name);
mi.setDateLoaned(date);
}

}

Option 2 :

  for(MediaItem mi : items)
{
if(mi.getTitle().equals(title))
{
mi.setLoanedTo(name);
mi.setDateLoaned(date);
}
}

The advantage of Option 1 over Option 2 is that if say in future you decide to modify the arraylist as you are iterating through it (eg: delete MediaItem object when the title matches) then you wont be able to do that in Option 2 (for-each). On the other hand Option 2 is very compact and less verbose as compared to Option 1

Understanding Java Iterator

It is pretty simple, actually

while(iterator.hasNext()){
if(collection2.contains(iterator.next()))
System.out.println("duplicate");
}

Imagine that the iterator is a pointer to an element of your list.

When you call next(), you're moving this pointer one step ahead.

If you don't move the pointer, hasNext() will always be true because you're still in the beginning of the list.

So you have to call the iterator's next() until there isn't any remaining element in the list.

How to use an iterator in this case?

Use two iterators. I tested this and it worked for me.

    Iterator<Integer> first = li.listIterator();

// Will raise IndexOutOfBoundsException if list is empty.
Iterator<Integer> second = li.listIterator(1);

while (second.hasNext()) {
System.out.println(first.next() + " " + second.next());
}

Edit: No need for inner if. Silly me.

Explanation: the listIterator(index) method returns an iterator that starts at the specified position in the list where as listIterator() returns an iterator that starts at position zero.

The first iterator therefore starts at 0 and the second starts at 1. Then it is merely a question of printing the next() on both. This will work irrespective of whether the number of elements in the list is odd or even.

Edit 2

My logic fu is very weak today. Thanks @barjak for pointing out the case about the empty list and the unnecessary first.hasNext().

Iterator vs for

First of all, there are 2 kinds of for loops, which behave very differently. One uses indices:

for (int i = 0; i < list.size(); i++) {
Thing t = list.get(i);
...
}

This kind of loop isn't always possible. For example, Lists have indices, but Sets don't, because they're unordered collections.

The other one, the foreach loop uses an Iterator behind the scenes:

for (Thing thing : list) {
...
}

This works with every kind of Iterable collection (or array)

And finally, you can use an Iterator, which also works with any Iterable:

for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
...
}

So you in fact have 3 loops to compare.

You can compare them in different terms: performance, readability, error-proneness, capability.

An Iterator can do things that a foreach loop can't. For example, you can remove elements while you're iterating, if the iterator supports it:

for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
if (shouldBeDeleted(thing) {
it.remove();
}
}

Lists also offer iterators that can iterate in both directions. A foreach loop only iterates from the beginning to an end.

But an Iterator is more dangerous and less readable. When a foreach loop is all you need, it's the most readable solution. With an iterator, you could do the following, which would be a bug:

for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
System.out.println(it.next().getFoo());
System.out.println(it.next().getBar());
}

A foreach loop doesn't allow for such a bug to happen.

Using indices to access elements is slightly more efficient with collections backed by an array. But if you change your mind and use a LinkedList instead of an ArrayList, suddenly the performance will be awful, because each time you access list.get(i), the linked list will have to loop though all its elements until the ith one. An Iterator (and thus the foreach loop) doesn't have this problem. It always uses the best possible way to iterate through elements of the given collection, because the collection itself has its own Iterator implementation.

My general rule of thumb is: use the foreach loop, unless you really need capabilities of an Iterator. I would only use for loop with indices with arrays, when I need access to the index inside the loop.



Related Topics



Leave a reply



Submit