简体   繁体   中英

Java - How do I refer to the previous and next element during an iteration?

When I have a for loop , I use the i to refer to the elements of my array, objects, etc.

Like:
Current item: myArray[i]
Next item: myArray[i+1]
Previous item: myArray[i-1]

But at the moment, I'm using a foreach loop ( for (Object elem : col) { ).
How do I refer to the previous item?
(I need to do a search an 'array', which I'm doing with for (Object object : getComponents()) .

But when it returns true (so it finds what I look for), it should perform the code on the previous and the next item.

Clarification: I have java.awt.Component elements!

If the data-structure is a List, then you can use a ListIterator directly. The ListIterator is special because it contains both the methods next() and previous()

List list = ...;
ListIterator iter = list.listIterator(); //--only objects of type List has this
while(iter.hasNext()){
    next = iter.next();
    if (iter.hasPrevious()) //--note the usage of hasPrevious() method
       prev = iter.previous(); //--note the usage of previous() method
}

The foreach loop won't let you do that. My suggestion is to go back to using the good old fashioned Iterator . For example

final Iterator itr=getComponents().iterator();
Object previous=itr.next();
Object current=itr.next();
while(itr.hasNext()){
    Object next=itr.next();
    //Do something with previous, current, and next.
    previous=current;
    current=next;
}
JButton prev, next, curr;
Component[] arr = getComponents();

for(int i=1;i<arr.length-1;i++) {
    if (yourcondition == true) {
        curr = (JButton) arr[i];
        prev = (JButton) arr[i-1];
        next = (JButton) arr[i+1];
    }
}

Array indexing

If you have an array-like data-structure (eg an actual array or something like an ArrayList ), then referencing i , i-1 , i+1 will give good performance so there isn't much more to it. (Although having to turn a For-Each Loop into an index counting For Loop isn't very fun and is one of the few caveats.)

The answer offered by Sergey does something like this.

The versatile ListIterator

If you can get your hands on an ListIterator (which is actually quite a big assumption), the answer offered by Suraj could suffice. But do note both next() and previous() moves the iterator position . So if you did something like the following for each loop iteration: prev = previous(); current = next(); next = next(); previous() prev = previous(); current = next(); next = next(); previous() prev = previous(); current = next(); next = next(); previous() , you'll end up performing roughly 4 iteration operations per loop. This isn't much of a problem if iteration is cheap , and luckily this is often the case for data-structures that offers a ListIterator .

Generic solution

The generic solution for any Iterable (or Iterator ) should make no random lookups (as is possible with an array) or make assumptions regarding performance of next() , which should be called at most N times where N is the number of available elements.

Here's one such implementations:

final Iterator<E> it = iterable.iterator();

for (E next = (it.hasNext() ? it.next() : null), current = null; next != null;) {
    E previous = current;
    current = next;
    next = it.hasNext() ? it.next() : null;

    // Do something using 'current', 'previous' and 'next'.
    // NB: 'previous' and/or 'next' are null when 'current' is
    // the first and/or last element respectively
}

Mind, this implementation has caveats of its own:

  • It'll break if Iterable contains null elements.
  • Neither current or next are effectively-final , so cannot be used directly in them fangled Java 8 lambdas.

I did this to access the previous and next elements in a list while using enhanced for loop.

Here's a quick snippet:

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

class Scratch {

  public static void main(String[] args) {
    List<Integer> myInts = new ArrayList<>();
    myInts.add(1);
    myInts.add(2);
    myInts.add(3);
    myInts.add(4);
    myInts.add(5);

    Integer next = null;
    Integer previous = null;

    for (Integer current: myInts) {
        try {
                previous = myInts.get(myInts.indexOf(current)-1);
            } catch (IndexOutOfBoundsException ignored){
               // ignored
            }
        try {
                next = myInts.get(myInts.indexOf(current)+1);
            } catch (IndexOutOfBoundsException ignored){
                next = null;
            }
        System.out.println("previous = " + previous);
        System.out.println("current = " + current);
        System.out.println("next = " + next);
    }
  }
}

Output:

previous = null
current = 1
next = 2
previous = 1
current = 2
next = 3
previous = 2
current = 3
next = 4
previous = 3
current = 4
next = 5
previous = 4
current = 5
next = null

Yeah! I know, the code's ugly. But, it get's the job done.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM