3

hi a normal iterator for a LinkedList would be the following, however, how do we build an iterator that returns an iterator starting at a specified index? How do we build:

public Iterator<E>iterator(int index)???  

thanks! normal Iterator:

    public Iterator<E> iterator( )
    {
        return new ListIterator();
    }

private class ListIterator implements Iterator<E>
    {
        private Node current;

        public ListIterator()
        {
            current = head; // head in the enclosing list
        }
        public boolean hasNext()
        {
            return current != null;
        }
        public E next()
        {
            E ret = current.item;
            current = current.next;
            return ret;
        }
        public void remove() { /* omitted because optional */ }
    }
Katherine
  • 257
  • 2
  • 6
  • 15
  • If you don't plan to remove elements from your `Colleciton` while iterating, you rather just use a traditional `for` loop. – Chetan Kinger May 08 '15 at 12:53
  • LinkedList has a method `listIterator(int)` it does exactly what you want. Here is [link to docs](https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#listIterator(int)) – Anton Feb 02 '18 at 09:25

2 Answers2

4

Well you could just call the normal iterator() method, then call next() that many times:

public Iterator<E> iterator(int index) {
    Iterator<E> iterator = iterator();
    for (int i = 0; i < index && iterator.hasNext(); i++) {
        iterator.next();
    }
    return iterator;
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Wouldn't you rather just iterate through the collection using a traditional `for` loop and skip the indexes you are not interested in? – Chetan Kinger May 08 '15 at 12:42
  • @ChetanKinger: I'm not sure what you mean - this isn't a method I'd usually write, but it answers the question that was asked... – Jon Skeet May 08 '15 at 12:43
  • I'll try to elaborate through code : `for(int i=0;iindex) { break; } else { //dosomething } }`. Why create an iterator in the first place? Only reason this would make sense is if you plan to remove elements while iterating. – Chetan Kinger May 08 '15 at 12:45
  • @JonSkeet thank u Jon! great help, you are a legend! – Katherine May 08 '15 at 12:48
2

This is kick-off example how to implement such iterator, but it's advised also to create or extend appropriate interface and make this object implementing this interface for convention.

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

public class IterableObject {

    private List<String> values = new ArrayList<String>();


    public Iterator<String> getIterator(final int index) {

        Iterator<String> it = new Iterator<String>() {

            private int current = index;

            @Override
            public void remove() {
                // TODO Auto-generated method stub

            }

            @Override
            public String next() {
                String value = values.get(current);
                current++;
                return value;
            }

            @Override
            public boolean hasNext() {
                if(values.size() > current){
                    return true;
                }else{
                    return false;
                }

            }
        };

        return it;
    }

}

UPDATE

According to comments I've written an Iterator for LinkedList

public Iterator<String> getIterator(final int index) {


        Iterator<String> it = new Iterator<String>() {

            private Object currentObject = null;

            {
                /*initialize block where we traverse linked list 
                  that it will pointed to object at place index*/
                System.out.println("initialize" + currentWord);
                for(int i = 0; currentObject.next != null && i < index; i++, currentObject = currentObject.next)
                    ;

            } 


            @Override
            public void remove() {
                // TODO Auto-generated method stub

            }

            @Override
            public String next() {
                Object obj = currentObject.next;
                currentObject = currentObject.next;
                return obj;
            }

            @Override
            public boolean hasNext() {
                return currentObject.next != null;

            }
        };

        return it;
    }

Because Iterator is object of Anonymous class we can't use constructor but can initialise it in initialise block look at this answer: https://stackoverflow.com/a/362463/947111 We traverse it once at the beginning (sorry for C style) so it will point to currentObject. All remain code is self explained.

Community
  • 1
  • 1
Anatoly
  • 5,056
  • 9
  • 62
  • 136
  • @ChetanKinger, yes I've made mistake and fixed it already. Thank you for pointing me to that. – Anatoly May 08 '15 at 13:07
  • 1
    Just tried out your code and it works as advertised. This is a better way to do it than the accepted answer IMO. – Chetan Kinger May 08 '15 at 13:07
  • @ChetanKinger, ups I accidentally deleted your comment :( Sorry – Anatoly May 08 '15 at 13:08
  • This would be extremely inefficient for a linked list since `values.get(index)` needs to traverse the list from the start every time it is executed to get the specified element. – Lii May 08 '15 at 13:09
  • The `hasNext` method could be written more succinctly with a body like this: `return values.get(current) != null;`. – Lii May 08 '15 at 13:09
  • @Lii Still better than the accepted answer as it will perform better in some situations. – Chetan Kinger May 08 '15 at 13:10
  • @Lii, `values.get(current)` throws out of bound exception when its index is greater then size of an internal array. – Anatoly May 08 '15 at 13:10
  • I think you have misunderstood my comment. – Lii May 08 '15 at 13:11
  • @ChetanKinger: You're right, it's better for array based lists. But it's really not suitable for linked lists. – Lii May 08 '15 at 13:17
  • @Anatoly Only moderators can delete comments from other users. I believe I deleted mine accidently :). Also. what @Lii said is an alternate option. `hasNext` could simply return `values.get(current)!=null` but that would require the client code to handle the exception or crash instead. I still prefer your way of doing it. – Chetan Kinger May 08 '15 at 13:24