Concise Java Solution


  • 103
    C
    class PeekingIterator implements Iterator<Integer> {  
        private Integer next = null;
        private Iterator<Integer> iter;
    
        public PeekingIterator(Iterator<Integer> iterator) {
            // initialize any member here.
            iter = iterator;
            if (iter.hasNext())
                next = iter.next();
        }
        
        // Returns the next element in the iteration without advancing the iterator. 
        public Integer peek() {
            return next; 
        }
    
        // hasNext() and next() should behave the same as in the Iterator interface.
        // Override them if needed.
        @Override
        public Integer next() {
            Integer res = next;
            next = iter.hasNext() ? iter.next() : null;
            return res; 
        }
    
        @Override
        public boolean hasNext() {
            return next != null;
        }
    }
    

    cache the next element. If next is null, there is no more elements in iterator.

    Edit: check AlexTheGreat's answer. It's better.


  • 0
    H

    good job!..............


  • 4
    W

    How can "next" be updated? I think it will equal to "null" forever. Can anyone help me here?


  • 0
    E

    @whitecatgsd next is updated in the next() method, i.e., when the iterator is exhausted, next() is updated to null; otherwise, it is updated to the next value of the iterator.


  • 0
    W

    @GWTW But "int next" is initialized as "null", and in "next()", it calls "hasnext()" right? If next is initialized with "null", "hasNext" will always return false and therefore "next()" will never update variable next. This is how I read the code, but I know I got something wrong here. Pls correct me.


  • 0
    E

    @whitecatgsd Yes, next is initialized as null, but is updated to be the first element of the iteratorin the constructor if iterator is nonempty. Similarly,

    next = iter.hasNext() ? iter.next() : null;
    

    is updating next to iter's next element if iter still has such one.


  • 0
    D

    I don't think we need to check iter.hasNext() in the constructor.


  • 10
    L

    I have the same question at first, then I notice the iter is defined as Iterator NOT PeekIterator, so it will use the hasNext method in java, not the one we write in this PeekIterator class


  • 16
    A

    I used the exactly same solution. But I do feel using null to check if we have reached the end of iterator is not 100% right. In theory, null could be a valid element.
    An slightly alternative approach to use boolean indicating end of iterator:

    private Integer next;
    private Iterator<Integer> itr;
    private boolean done = false;

    public PeekingIterator(Iterator<Integer> iterator) {
        itr = iterator;
        if (iterator.hasNext())
            next = itr.next();
        else
            done = true;
    }
    
    // Returns the next element in the iteration without advancing the iterator.
    public Integer peek() {
        return next;
    }
    
    // hasNext() and next() should behave the same as in the Iterator interface.
    // Override them if needed.
    @Override
    public Integer next() {
        Integer result = next;
        if (itr.hasNext()) {
            next = itr.next();
        } else {
            next = null;
            done = true;
        }
        return result;
    }
    
    @Override
    public boolean hasNext() {
        return !done;
    }

  • 2
    M

    why don't you need to throw a NoSuchElementException if you call next when it does not have next?


  • 0
    Z

    It confused me for a long time, good catch!


  • 1

    Same idea. Perhaps we could reuse next() in constructor.

    public class PeekingIterator implements Iterator<Integer> {
    
        private Iterator<Integer> it;
    
        private Integer next;
    
        public PeekingIterator(Iterator<Integer> iterator) {
            it = iterator;
            next();
        }
        // ......
    }
    

  • 0
    R

    @whitecatgsd : it is updated in the constructor next = iter.next();


  • 1
    R

    @whitecatgsd iter.hasNext() is different with PeekingIterator.hasNext().


  • 1
    X

    I have a question. When we go to the last element N in the iterator, at this time N is still an Integer, but the next iterator of it will be NULL. Do we consider NULL is the next of N? And N hasNext() == true???? Thanks


  • 0
    O

    That moment that you think you've found a great solution, but somebody else published it "about a year ago".


  • 0
    O

    I'll put it out there nevertheless. It's slightly different.

    class PeekingIterator implements Iterator<Integer> {
    
        Integer me;
        Iterator <Integer> myIter;
    	public PeekingIterator(Iterator<Integer> iterator) {
    	    myIter = iterator;
    	    me = (myIter.hasNext()) ? myIter.next() : null;
    	}
    
    	public Integer peek() {
            return me;
    	}
    
    	@Override
    	public Integer next() {
    	    if (me == null) return null;
    	    Integer result = me;
    	    me = (myIter.hasNext()) ? myIter.next() : null;
    	    return result;
    	}
    
    	@Override
    	public boolean hasNext() {
    	    return (me != null || myIter.hasNext()) ;
    	}
    }
    

  • 0
    M

    This solution does not work for generic types. What if you want to store a null value in the iterator? With this implementation it would tell you that the iterator does not have more values, even though it does have!

    I coded an alternative solution that does handle the case where the iterator contains null values.


  • 0
    P

    @larryliu0104 Thanks! I was about to ask the exact same thing as well.


  • 0

    It doesn't seem problem statement specifies the underlying data structure that implements the iterator.
    Can we simply do A or B? This shouldn't be a correct solution.
    A:

    class PeekingIterator implements Iterator<Integer> {
    
        LinkedList<Integer> iter = new LinkedList<>(); 
        
    	public PeekingIterator(Iterator<Integer> iterator) {
    	    while (iterator.hasNext()) 
    	        iter.offer(iterator.next());   
    	}
    
    	public Integer peek() {
                return iter.peek(); 
    	}
    
    	@Override
    	public Integer next() {
    	    return iter.poll(); 
    	}
    
    	@Override
    	public boolean hasNext() {
    	    return !iter.isEmpty(); 
    	}
    }
    

    B:

    class PeekingIterator implements Iterator<Integer> {
    
        Queue<Integer> iter = new LinkedList<>(); 
        
    	public PeekingIterator(Iterator<Integer> iterator) {
    	    while (iterator.hasNext()) 
    	        iter.offer(iterator.next());   
    	}
    
    	public Integer peek() {
                return iter.peek(); 
    	}
    
    	@Override
    	public Integer next() {
    	    return iter.poll(); 
    	}
    
    	@Override
    	public boolean hasNext() {
    	    return !iter.isEmpty(); 
    	}
    }

Log in to reply
 

Looks like your connection to LeetCode Discuss was lost, please wait while we try to reconnect.