36

I'm iterating an ArrayList using the for each loop, but I don't know how to get the current index where the loop is.

I did Google it, but I couldn't find anything helpful.

Please, if someone could tell me how to get the current index, I'll be grateful.

Jeffrey Kevin Pry
  • 3,266
  • 3
  • 35
  • 67
Renaud is Not Bill Gates
  • 1,684
  • 34
  • 105
  • 191

6 Answers6

49

Just use a traditional for loop:

for (int i = 0; i < yourArrayList.size(); i ++) {
    // i is the index
    // yourArrayList.get(i) is the element
}
tckmn
  • 57,719
  • 27
  • 114
  • 156
  • 1
    Sometimes the old ways are the best ways, especially since the traditional for loop has well defined behavior. Bonus points if you can answer this, why are the traditional for loop variables are i,j,k? – Michael Shopsin Jun 20 '16 at 14:45
  • 2
    "i" was used to sum up the word "index" in algorithm, and "j" and "k" following the alphabet. – Karpinski Aug 28 '17 at 14:32
13

To steal doorknobs answer but make a change that otherwise would drive me nuts like a pirate:

int arraySize = yourArrayList.size();
for (int i = 0; i < arraySize; i ++) {
    // i is the index
    // yourArrayList.get(i) is the element
}

alternatively

int currentPosition = 0;
for (myItemType myItem :myArrayList) {
    // do stuff

    currentPosition++;
}
Zak
  • 24,947
  • 11
  • 38
  • 68
  • 2
    Why would this make you nuts? Your change would make me nuts! – Java Devil Jan 07 '14 at 00:09
  • why call the size function each time through the loop? call it once, get the answer, then use the answer. It's the intent of what you are trying to do, without all the extra function calls. – Zak Jan 07 '14 at 00:15
  • Your post is incorrect: from the docs: Iterator iterator() Returns an iterator over the elements in this list in proper sequence. – Zak Jan 07 '14 at 00:29
  • You're right. I was relying on my memory which isn't the sharpest thing. – Reut Sharabani Jan 07 '14 at 00:45
  • 2
    If you are coding for Android, the docs strongly recommend @Zak's way of doing it precisely to avoid the repetitive function call. If you change the size of the list inside the loop, you can `arraySize=yourArrayList.size()` or use `++` or `--` as needed. – nexus_2006 Jan 07 '14 at 01:41
  • @nexus_2006 (I) they do for devices without JIT (ii) the question isn't tagged android (iii) there is no "extra function call" on any r/d-ecent JVMs. – assylias Jan 07 '14 at 08:16
  • 2
    @assylias - across programming languages, compilers, and platforms, it's not clear which compilers/VMs may optimize out the repeat function calls from inside the for loop. Further, the code isn't written in a way that shows intent to NOT repeatedly make that function call. This is why it drives me nuts, and why I put the function call on a single line by itself so I can semantically tell my intent with no optimization guessing by the compiler. – Zak Jan 08 '14 at 19:17
  • 2
    The issue is a lot more subtle I think. If the list will never change size during the loop there's no need to repeatedly call the size method. I would be surprised if the repeated call to size also can be optimized away by the VM as it would have to prove that no modifications can happen to the list during the loop (reference counting maybe?). I tested this a while back and the repeated call wasn't optimized away, perhaps it is now. I use `for( int i =0, n = list.size(); i – wobblycogs Jan 22 '15 at 10:20
  • @wobblycogs you'd get a `ConcurrentModificationException` if you tried to change the size while iterating. – OrangeDog May 06 '21 at 13:51
8

You can use list.indexOf(objectYouWantToFind); to get its index if it is in the container else you will receive -1 as a result.

Omar Abdelrahman
  • 325
  • 4
  • 11
  • 1
    this is exactly the precise answer for the above question and i dont get why it is not up-voted the most – robel Apr 19 '16 at 13:14
  • 4
    @robel an issue with `indexOf` is one of performance. `indexOf` does a linear scan of all elements every time you call it, while @Doorknob's answer with the explicit for loop avoids the extra scanning. For example, if you are iterating through a loop and calling indexOf every time, you have O(n^2). Doorknob's answer is O(n) if you consider `get` as O(1). This link might be of interest to you: http://java-performance.info/arraylist-performance/ – Alex Gaudio Jun 06 '17 at 18:01
  • @robel It also doesn't work if the object is not unique. – OrangeDog May 06 '21 at 13:50
2

Use a traditional loop. For-each statements in java do not promise an order over the collection. The only way to actually know the index is to query the list on every iteration.

for(int i=0; i<list.size; i++){
    // you have your index, i
    // the item is at list.get(i)
}

Relying on the iterator() implementation you can also use an alternative (+1 Zak in the comments):

int position = 0;
for(Item i : list){

    // do stuff with `i`

    // increase position as the last action in the loop
    position++;
}

From the docs: Iterator<E> iterator() Returns an iterator over the elements in this list in proper sequence

Here is why I usually don't use the short form of for:

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


public class MyList<T> extends ArrayList<T> {
    // the main function to run the example
    public static void main(String[] args){
        // make a list of my special type
        MyList<Integer> list = new MyList<Integer>();

        // add 10 items to it
        for (int i =0; i<10; i++){
            list.add(i);
        }

        // print the list using the for-each mechanism (it's actually an iterator...)
        for (Integer i : list){
            System.out.println(i);
        }
    }

    // I like lists that start at 3!
    // make my list return an iterator in the middle of the list...
    @Override
    public Iterator<T> iterator(){
        return this.listIterator(3);

    }

}

Obviously, you'd expect having the first item on the first iteration, and this is clearly not the case because an iterator can be implemented in many ways and Java's foreach is depending on the underlying iterator implemetation.

Also, you have to use position++ in the end of your loop which is probably error-prone (don't know, don't usually use it..).

That said, it does improve readability like mentioned in this stackoverflow question about Java's foreach.

For more information, see How does the Java for each loop work?.

Community
  • 1
  • 1
Reut Sharabani
  • 30,449
  • 6
  • 70
  • 88
  • 1
    This is incorrect: from the docs: Iterator iterator() Returns an iterator over the elements in this list in proper sequence. The given example above would be a buggy overridden implementation of the spec. The problem would not be in using the iterator, it would be a bug in implementing the definition of iterator(). – Zak Jan 07 '14 at 00:29
  • @Zak Thanks, so any reason not to use the "currentPosition" solution with for-each? – Reut Sharabani Jan 07 '14 at 00:34
0

If it's iterating a List, you can use the method indexOf(), example:

List<Animal> animals = new ArrayList<Animal>();
Animal a = new Animal();
a.setAnimalCode(1);
animals.add(a);

a = new Animal();
a.setAnimalCode(35);
animals.add(a);

a = new Animal();
a.setAnimalCode(12);
animals.add(a);

for(Animal a: animals)
   if(animal.getAnimalCode()==35)
      System.out.println("Index of chosen one: "+animals.indexOf(a));

Index of chosen one: 2

Maelo
  • 11
  • 1
0

Kind of a hack, but you can surely have an index in a for each loop :

public class Counter{
  private Integer i;
  public Counter(Integer i) { this.i = i; }
  public void incrementOne(){ this.i = getI() + 1; }
  //getter and setter for i
}

And, somewhere else in your for each loop :

Alien.java

Counter counter = new Counter(0);
List<String> list = new ArrayList<>();
//have some values in the list
list.forEach(i-> {
  //i will have the value and the counter will have the count!
  System.out.println(counter.getI());
  counter.incrementOne();
});

Otherwise, you always have a list.indexOf(i), where i is each object in the list. :P

aayoustic
  • 99
  • 9