113

I am using an Iterator to iterate through a collection and I want to get the current element's index.

How can I do that?

Willi Mentzel
  • 21,499
  • 16
  • 88
  • 101
Mahmoud Saleh
  • 31,861
  • 113
  • 313
  • 484
  • 1
    possible duplicate of [Is there a way to access an iteration-counter in Java's for-each loop?](http://stackoverflow.com/questions/477550/is-there-a-way-to-access-an-iteration-counter-in-javas-for-each-loop) – finnw Jul 25 '10 at 16:10
  • 1
    @finnw I do not think that they are duplicate. This question is asking using Iterator, the other is using for-each loop. Both questions are solved by similar approach, so the answers are duplicate not the question. – Robert Jun 03 '14 at 11:03

12 Answers12

128

I had the same question and found using a ListIterator worked. Similar to the test above:

List<String> list = Arrays.asList("zero", "one", "two");

ListIterator<String> iter = list.listIterator();
    
while (iter.hasNext()) {
    System.out.println("index: " + iter.nextIndex() + " value: " + iter.next());
}

Make sure you call the nextIndex() before you actually get the next().

Nicolapps
  • 559
  • 6
  • 24
Paul
  • 1,289
  • 1
  • 8
  • 2
  • 7
    Thanks for mentioning 'Make sure you call the nextIndex BEFORE you actually get the next()' – Gangadhar JANNU Dec 22 '16 at 11:27
  • Thanks, I didn't know about this before. The caution I would make is that ListIterator is bidirectional whereas Iterator is unidirectional. As long as you avoid moving back and forth with what is effectively a cursor, then you should be safe. – user2910265 Jan 10 '20 at 00:35
100

Use your own variable and increment it in the loop.

om-nom-nom
  • 60,231
  • 11
  • 174
  • 223
Chris Diver
  • 18,522
  • 4
  • 44
  • 58
  • 7
    But also see @mateusz-dymczyk suggestion about `it.nextIndex()`. Useful when the collection is a List. – noamtm Sep 06 '16 at 08:57
29

Here's a way to do it using your own variable and keeping it concise:

List<String> list = Arrays.asList("zero", "one", "two");

int i = 0;
for (Iterator<String> it = list.iterator(); it.hasNext(); i++) {
    String s = it.next();
    System.out.println(i + ": " + s);
}

Output (you guessed it):

0: zero
1: one
2: two

The advantage is that you don't increment your index within the loop (although you need to be careful to only call Iterator#next once per loop - just do it at the top).

Tom Clift
  • 2,287
  • 23
  • 18
  • 3
    If you create the iterator yourself you can use a ListIterator as well and do not need the separate int variable. – Robert Klemme Aug 20 '12 at 07:14
  • 1
    If you use a 'static import' for Arrays.asList then you can just write `asList("zero", "one", "two")` – karmakaze Jun 23 '15 at 15:48
  • that is exactly the way i did it before i read the answer of Paul. I would strongly discourage your way, because I don't see any advantage to it. Do you think there is an advantage (except for the one mentioned). Why didn't you use a for-each loop? Defining the Iterator explicitely is not necessary, if you use your own variable. – Willi Mentzel May 20 '16 at 08:08
  • @progressive_overload just if you need an Iterator (as per question, e.g. to pass to library), which the example doesn't show. In this example you have a variable outside the loop and need to be careful to call #next once. In Paul's example there are no variables outside the loop, but you need to be careful to call #next and #nextIndex together once (and in practice, if used more than once, they would be pulled into local variables, which that example doesn't show). – Tom Clift May 28 '16 at 05:05
23

You can use ListIterator to do the counting:

final List<String> list = Arrays.asList("zero", "one", "two", "three");

for (final ListIterator<String> it = list.listIterator(); it.hasNext();) {
    final String s = it.next();
    System.out.println(it.previousIndex() + ": " + s);
}
Mihir Trivedi
  • 1,260
  • 15
  • 36
Robert Klemme
  • 2,063
  • 17
  • 20
12

What kind of collection? If it's an implementation of the List interface then you could just use it.nextIndex() - 1.

Willi Mentzel
  • 21,499
  • 16
  • 88
  • 101
Mateusz Dymczyk
  • 14,171
  • 8
  • 55
  • 90
4

Use an int and increment it within your loop.

Carl Smotricz
  • 62,722
  • 17
  • 119
  • 161
Florian Reischl
  • 3,678
  • 1
  • 20
  • 18
3

just do something like this:

        ListIterator<String> it = list1.listIterator();
        int index = -1;
        while (it.hasNext()) {
            index++;
            String value = it.next();
            //At this point the index can be checked for the current element.

        }
Sunny
  • 6,720
  • 19
  • 56
  • 92
3

Use a ListIterator to iterate through the Collection. If the Collection is not a List to start with use Arrays.asList(Collection.toArray()) to turn it into a List first.

BuZZ-dEE
  • 3,875
  • 7
  • 48
  • 76
Jatin
  • 709
  • 4
  • 5
1

All you need to use it the iterator.nextIndex() to return the current index that the iterator is on. This could be a bit easier than using your own counter variable (which still works also).

public static void main(String[] args) {    
    String[] str1 = {"list item 1", "list item 2", "list item 3", "list item 4"};
    List<String> list1 = new ArrayList<String>(Arrays.asList(str1));

    ListIterator<String> it = list1.listIterator();

    int x = 0;

    //The iterator.nextIndex() will return the index for you.
    while(it.hasNext()){
        int i = it.nextIndex();
        System.out.println(it.next() + " is at index" + i); 
    }
}

This code will go through the list1 list one item at a time and print the item's text, then "is at index" then it will print the index that the iterator found it at. :)

Ryan
  • 1,848
  • 3
  • 20
  • 31
  • 1
    Actually, your code is off by one because it attempts to display the index AFTER calling it.next(). – Henrik Aasted Sørensen Jan 23 '14 at 11:17
  • 1
    @HenrikAastedSørensen My code is not off by one, but I can understand why it might seem that way. The first time it.next() is called it will return the list item at index 0. Go ahead and run the code and you will see, it works just fine :) – Ryan May 12 '21 at 15:48
1

See here.

iterator.nextIndex() would provide index of element that would be returned by subsequent call to next().

Willi Mentzel
  • 21,499
  • 16
  • 88
  • 101
Jolly
  • 19
  • 1
  • The interface Iterator has NOT nextIndex() method. You need to explicitly use a ListIterator for that, but the OP questioned specifically about Iterator. – Fran Marzoa Feb 21 '18 at 11:10
0

Though you already had the answer, thought to add some info.

As you mentioned Collections explicitly, you can't use listIterator to get the index for all types of collections.

List interfaces - ArrayList, LinkedList, Vector and Stack.

Has both iterator() and listIterator()

Set interfaces - HashSet, LinkedHashSet, TreeSet and EnumSet.

Has only iterator()

Map interfaces - HashMap, LinkedHashMap, TreeMap and IdentityHashMap

Has no iterators, but can be iterated using through the keySet() / values() or entrySet() as keySet() and entrySet() returns Set and values() returns Collection.

So its better to use iterators() with continuous increment of a value to get the current index for any collection type.

Vignesh Raja
  • 5,592
  • 1
  • 25
  • 32
0

This would be the simplest solution!

std::vector<double> v (5);

for(auto itr = v.begin();itr != v.end();++itr){

 auto current_loop_index = itr - v.begin();

  std::cout << current_loop_index << std::endl;

}

Tested on gcc-9 with -std=c++11 flag

Output:

0
1
2
3
4

Brian Tompsett - 汤莱恩
  • 5,195
  • 62
  • 50
  • 120
Pal
  • 787
  • 8
  • 20