1

I would like to write Iterator over array with boolean flags. My class implements interface Iterable. Main idea of class is implement Integer subarray. For example, I would like to put numbers between 10 and 20 in array. If number is in array, there will be true inits place in array. Number 10 has index 0 in array, etc.

I wrote this subclass:

private class RangeIter implements Iterator<Integer> {

    private int currentIndex = 0;

    @Override
    public boolean hasNext() {
        return currentIndex < size;  


    }

    @Override
    public Integer next() {
        if (!hasNext()) {
            throw new NoSuchElementException("No elements more!");
        }
        Integer element = currentIndex;
        if (!elementFlags[currentIndex]) {
            currentIndex++;
        }
        return element + lowerBound;
    }
}

Variables used in this piece of code are: lowerBound: lower possible element in array size: size of array (upperBound - lowerBound +1 )

My question is: Why this iterator doesn't work?

Here is rest of my code:

public class FixedRangeIntegerSet implements Iterable<Integer> {

    private boolean[] elementFlags;
    private int size;
    private int lowerBound;
    private int upperBound;

    public FixedRangeIntegerSet(int lowerBound, int upperBound) {
        this.lowerBound = lowerBound;
        this.upperBound = upperBound;
        int size = upperBound - lowerBound + 1;
        elementFlags = new boolean[size + 1];
        this.size = size;
    }

    public FixedRangeIntegerSet(int lowerBound, int upperBound, Iterable<Integer> elements) {
        int sizeCopy = size;
        for (Integer element : elements) {
            if (sizeCopy > 0) {
                add(element);
                sizeCopy--;
            }
        }
    }

    public FixedRangeIntegerSet(int lowerBound, int upperBound, Integer... elements) {
        for (int i = 0; i < elements.length; i++) {
            add(elements[i]);
        }
    }

    public boolean add(Integer element) {
        if (elementFlags[element - lowerBound] == true) {
            return false;
        }
        elementFlags[element - lowerBound] = true;
        return true;
    }

    public boolean containsElement(Integer element) {
        if (element < lowerBound || element > upperBound) {
            return false;
        }
        if (elementFlags[element - lowerBound] == true) {
            return true;
        } else
            return false;
    }

    public int getSize() {
        int size = 0;
        for (Boolean i : elementFlags) {
            if (i == true) {
                size++;
            }
        }
        return size;
    }

    public int getLowerBound() {
        return lowerBound;
    }

    public int getUpperBound() {
        return upperBound;
    }

    public boolean remove(Integer element) {
        if (elementFlags[element - lowerBound] == false) {
            return false;
        } else {
            elementFlags[element - lowerBound] = false;
            return true;
        }
    }
1
  • where do you get the size? Commented Dec 3, 2015 at 7:07

2 Answers 2

2

You are not giving us all the relevant code, but just from your hasNext and next methods I can see some issues :

  1. currIndex is only advanced if elementFlags[currentIndex] is false, which means your iterator will get stuck at the first index for which the array contains true.

  2. I think you want to loop over the indices until you find the next index for which the array contains true, and return that index.

  3. You should initialize the Iterator so that the initial currentIndex is such that elementFlags[currentIndex] is true.

A suggested implementation :

private class RangeIter implements Iterator<Integer> {

    private int currentIndex = 0;

    public RangeIter ()
    {
        currentIndex = 0;
        while (currentIndex < size && !elementFlags[currentIndex])
            currentIndex++;
    }

    @Override
    public boolean hasNext() {
        return currentIndex < size;  
    }

    @Override
    public Integer next() {
        if (!hasNext()) {
            throw new NoSuchElementException("No elements more!");
        }
        Integer element = currentIndex;
        while (currentIndex < size && !elementFlags[currentIndex]) {
            currentIndex++;
        }
        return element + lowerBound;
    }

}
Sign up to request clarification or add additional context in comments.

5 Comments

Yes, can you write me that, please?
@user5507755 The first 6 lines are the constructor of RangeIter. They don't close the class. I omitted the class declaration.
I get infinity loop when implement your iterator :/
@user5507755 Can you show your class that implements Iterable and the code that uses the iterator?
1

Is there a particular reason you're reinventing the wheel?

IntStream.range(lowerBound, upperBound).forEach(i -> doSomethingWith(i));

Or to access the elements of an array at these indexes:

Object[] someArray;
IntStream.range(lowerBound, upperBound)
    .map(i -> someArray[i])
    .forEach(obj -> doSomethingWith(obj));

2 Comments

If I understood the question correctly, the OP's class represents a non-contiguous range of integers - the boolean array determines which indices represent integers that should be iterated over.
@Eran maybe a filter is needed. Still, this sort of situation is why God invented streams and lambdas.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.