2
\$\begingroup\$

I am trying to implement the Iterable interface on an object, where the hasNext method on iterator will depend on mutable object state. This state is mutated by explicit function call after call to each next. Basically I am doing such implementation to keep it consistent across multiple implementation.

First implementation is external API base implementation, paginated API returns a token to determine if more pages are pending to be fetched.

Second implementation is: where we have a Collection of Objects, and we have to make an API call for each object in Collection.

Is such an implementation flawed? What can I do to improve this implementation?

public class MutableObject implements Iterable<MutableObject> {
    String personId;
    boolean initialCall;
    String tokenId;

    public MutableObject(String personId) {
        this.personId = personId;
        this.initialCall = true;
    }

    public MutableObject(String personId, boolean initialCall, String tokenId) {
        this.personId = personId;
        this.initialCall = initialCall;
        this.tokenId = tokenId;
    }

    public void updateState(String tokenId) {
        this.initialCall = false;
        this.tokenId = tokenId;
    }

    private MutableObject currentState() {
        return this;
    }

    private class MutableObjectIterator implements Iterator<MutableObject> {

        @Override
        public boolean hasNext() {
            return initialCall || Objects.nonNull(tokenId);
        }

        @Override
        public MutableObject next() {
            if(!hasNext()) {
                throw new NoSuchElementException("No more elements");
            }
            return currentState();
        }
    }
    @NotNull
    @Override
    public Iterator<MutableObject> iterator() {
        return new MutableObjectIterator();
    }

    public static void main(String[] args) {
        MutableObject mutableObject = new MutableObject(UUID.randomUUID().toString());
        int count = 0;
        String prevToken = null;
        Iterator<MutableObject> itr = mutableObject.iterator();
        while (itr.hasNext()) {
            MutableObject currState = itr.next();
            System.out.printf("[%d]: Curr State: %s\n", count, currState.toString());
            if(++count < 5) {
                prevToken = "DUMMY_TOKEN";
            } else {
                prevToken = null;
            }
            currState.updateState(prevToken);
        }
    }
}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ The Iterable interface does not place too many restrictions on how it is supposed to work but for me the fact that creating two iterators from the same iterable breaks the implementation is a bit problematic. I would try to place the mutable state into the Iterator and keep the immutable state in the Iterable. In a client side search this would mean that the search criteria are in the iterable and the token for the next batch would be updeated into the iterator. \$\endgroup\$ Jan 18 at 8:27
  • 1
    \$\begingroup\$ Welcome to Code Review! To help reviewers give you better answers, we need to know what the code is intended to be used for. Please add sufficient context to your question to describe the purpose of the code. We want to know why much more than how. The more you tell us about what your code is for, the easier it will be for reviewers to help you. Also, edit the title to simply summarise the task, rather than your concerns about the code. \$\endgroup\$ Jan 18 at 9:18
  • \$\begingroup\$ In "real life" is there guaranteed one mutation (updateState) call per iteration as you've shown? \$\endgroup\$
    – Reinderien
    Jan 18 at 14:21

0

Your Answer

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

Browse other questions tagged or ask your own question.