membersound
membersound

Reputation: 86777

How to iterate a list in both directions?

I have a list of objects and want to iterate in forwards and backwards, until an element is found that is "valid".

MyClass {
    private boolean valid;
    public boolean isValid() { return valid; }
}

List<MyClass> classes; //assume sorted list

Now I want to start at position idx, and iterate both forwards and backwards to find the closest element that is valid. So far I already got the forward algorithm working. But I feel that the code could be optimized:

//supposed to start at position X

int idx = 10;

//find the closest element that is valid
for (ListIterator<MyClass> itr = classes.listIterator(idx); itr.hasNext();) {
    if (itr.hasNext()) {
        MyClass my = itr.next();
        while (!my.isValid()) {
            if (itr.hasNext()) {
                my = itr.next();
            } else {
                break;
            }
        }
    }
    Sysout("the closest valid element is: " + my);
}

Could the iterator algorithm be written better?

Upvotes: 0

Views: 5488

Answers (3)

Ruchira Gayan Ranaweera
Ruchira Gayan Ranaweera

Reputation: 35567

You can use ListIterator#hasPrevious() and ListIterator#previous() for backward iteration and ListIterator#hasNext() and ListIterator#next() for forward iteration with ListIterator.

Upvotes: 0

bunty
bunty

Reputation: 234

      package iteratorPract;

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

public class MyIterClass {
    private boolean valid;

    public boolean isValid() {
        return this.valid;
    }

    public void setValid(boolean valid) {
        this.valid = valid;
    }

    public static void main(String[] args) {
        MyIterClass m1 = new MyIterClass();
        m1.setValid(true);
        MyIterClass m2 = new MyIterClass();
        List<MyIterClass> classes = new ArrayList<MyIterClass>();
        classes.add(m1);
        classes.add(m2);

        // from last
        ListIterator<MyIterClass> l1 = classes.listIterator(classes.size());

        while (l1.hasPrevious()) {
            if (l1.previous().isValid())
                System.out.println("it is valid");
            else
                System.out.println("not valid");
        }
        // from start
        ListIterator<MyIterClass> l2 = classes.listIterator();

        while (l1.hasNext()) {
            if (l1.next().isValid())
                System.out.println("it is valid");
            else
                System.out.println("not valid");
        }

    }

}

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726699

Use two iterators at the same time. Start both of them at idx, and advance each of them in each iteration of the loop, until you hit the limit:

ListIterator<MyClass> fwd = classes.listIterator(idx);
ListIterator<MyClass> bck = classes.listIterator(idx);
MyClass found = null;
while (fwd.hasNext() || bck.hasPrevious()) {
    if (fwd.hasNext()) {
        MyClass my = fwd.next();
        if (my.isValid()) {
            found = my;
            break;
        }
    }
    if (bck.hasPrevious()) {
        MyClass my = bck.previous();
        if (my.isValid()) {
            found = my;
            break;
        }
    }
}

If found is null at the end of the loop, no valid items were found. Otherwise, found contains the nearest item to idx. If two valid items are located at the same distance from idx, the item located forward would be returned.

Upvotes: 3

Related Questions