javalistiterator

How do I access ListIterator.previous() from another class


I have the following iteration in a "Statistics" Class

for (Number num : history) {
    // I do stuff with num here
    // ... and, occasionally want to read the previous value
} // for

Within my "history" class I have a ListIterator (rather than an Iterator as I want to go backwards as well).

   @Override
    public ListIterator<Number> iterator() {
       //System.out.println("In ITERATOR");
        ListIterator<Number> it = new ListIterator<Number>() {

            private int currentIndex = 0;

            @Override
            public boolean hasNext() {
                return currentIndex < gethistorySize() && spins.get(currentIndex) != null;
            }

            @Override
            public boolean hasPrevious() {
                return currentIndex > 0;
            }

            @Override
            public Number next() {
                return spins.get(currentIndex++);
            }

            @Override
            public Number previous() {
                if(hasPrevious()) {
                    return spins.get(currentIndex -1);
                }
                return null;
            }

            @Override
            public int previousIndex() {
                return currentIndex -1;

            }

            @Override
            public int nextIndex() {
                return currentIndex +1;
            }


            // The following functions are not implemented as we don't need them for this application
            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }

            @Override
            public void set(Number n) {
                throw new UnsupportedOperationException();
            }

            @Override
            public void add(Number n) {
                throw new UnsupportedOperationException();
            }

        };
        return it;
    }

... but I can't figure out, how I can get the previous element, when I am iterating through Numbers from the Statistics class.

Essentially, I want to iterate through Numbers but occasionally get the previous Number (after having moved past it).

I could store it, of course, but it seems that I should be able to call ListIterator.previous(), but I am unsure how to do that?

Any ideas?

G


Solution

  • Actually Kayaman already solved your problem using Iterator explicitly in two different ways.

    I just wrote a simple demo following your request:

    public class HelloWorld {
    public static void main(String... args) {
        int size = 5;
        History<Integer> history = new HelloWorld().new History<>(size);
        for (int i = 0; i < size; ++i) {
            history.add(Integer.valueOf(i));
        }
    
        for (Integer a : history) {
            System.out.println(a);
            if (a % 3 == 1) {
                System.out.println(history.iterator().previous());
            }
        }
    }
    
    class History<T> implements Iterable<T> {
        T[] arr;
        int index;
    
        public History(int theSize) {
            index = -1;
            arr = (T[]) new Object[theSize];
        }
    
        public void add(T t) {
            arr[++index] = t;
        }
    
        @Override
        public ListIterator iterator() {
            return new ListIterator() {
                int i = 0;
                @Override
                public boolean hasNext() {
                    return i <= index;
                }
    
                @Override
                public Object next() {
                    return arr[i++];
                }
    
                @Override
                public boolean hasPrevious() {
                    return i > 0;
                }
    
                @Override
                public Object previous() {
                    return arr[i - 1];
                }
    
                @Override
                public int nextIndex() {
                    return 0;
                }
    
                @Override
                public int previousIndex() {
                    return 0;
                }
    
                @Override
                public void remove() {
                    throw new UnsupportedOperationException();
                }
    
                @Override
                public void set(Object o) {
                    throw new UnsupportedOperationException();
                }
    
                @Override
                public void add(Object o) {
                    throw new UnsupportedOperationException();
                }
             };
          }
       }
    }
    

    And disasseambling its code, we have the following snippet:

      43: invokevirtual #9                  // Method com/company/HelloWorld$History.iterator:()Ljava/util/ListIterator;
      46: astore_2
      47: aload_2
      48: invokeinterface #10,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      53: ifeq          101
      56: aload_2
      57: invokeinterface #11,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      62: checkcast     #12                 // class java/lang/Integer
      65: astore_3
      66: getstatic     #13                 // Field java/lang/System.out:Ljava/io/PrintStream;
      69: aload_3
      70: invokevirtual #14                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      73: aload_3
      74: invokevirtual #15                 // Method java/lang/Integer.intValue:()I
      77: iconst_3
      78: irem
      79: iconst_1
      80: if_icmpne     98
      83: getstatic     #13                 // Field java/lang/System.out:Ljava/io/PrintStream;
      86: aload_1
      87: invokevirtual #9                  // Method com/company/HelloWorld$History.iterator:()Ljava/util/ListIterator;
      90: invokeinterface #16,  1           // InterfaceMethod java/util/ListIterator.previous:()Ljava/lang/Object;
      95: invokevirtual #14                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
    

    Clearly the for loop is actually using

    while(history.hasNext()) {
         history.next();
    }
    

    to iterate the history. So if you use history.iterator().previous() directly in the for loop, you are actually creating a new iterator which will start from the very beginning 0 in your case.

    And you don't want it, right?

    Explicitly using iterator will suit your case as follows:

        ListIterator<Integer> iterator = history.iterator();
        while(iterator.hasNext()) {
            int a = iterator.next();
            System.out.println(a);
            if (a % 3 == 1) {
                System.out.println(iterator.previous());
            }
    
        }