Переопределение Iterator в круговом массиве

Я пишу свой собственный класс Deque, и мне нужно переопределить итератор.

Пример: скажем, массив имеет вид [3,4,5,null,null,null,1,2], где 1 — начало, а 5 — конец. Мне нужно было бы использовать итератор, чтобы начать с 1 и закончить после 5.

Вот и весь мой Deque Class. Я считаю, что у меня все в порядке с итератором, кроме метода hasNext.

import java.util.Iterator;
import java.util.*;
import javax.swing.border.*;

public class Deque20<E> implements Iterable<E> {

    public final int INITIAL_SIZE = 16;

    private E[] items;
    private E[] temp;
    private int size;
    private int first;

    @SuppressWarnings("unchecked")  // Casting Object[] to E[]
    public Deque20() {
        items = (E[]) new Object[INITIAL_SIZE];
        size = 0;
        first = 0;
    }

    public void addFirst(E e){
        if(size == items.length){
            doubleSize();
        }
        first -= 1;
        if(first == -1){
            first = items.length - 1;
        }
        items[first] = e;
        size += 1;
    }

    public void addLast(E e){
        if(size == items.length){
            doubleSize();
        }
        items[(first + size) % items.length] = e;
        size++; 
    }

    public void removeFirst(){
        items[first] = null;
        first++;
        size--;
    }

    public void removeLast(){
        items[((first + size) % items.length) - 1] = null;
        size--;
    }

    public E peekFirst(){
        if(size == 1){
            return items[first];
        }else{
            return items[first];
        }
    }

    public E peekLast(){
        if(size == 1){
            return items[first];
        }else{
            return items[((first + size) % items.length) - 1];
        }
    }

    @SuppressWarnings("unchecked")
    private void doubleSize(){
        temp = (E[]) new Object[size * 2];
        for(int i = 0; i < size; i++){
            temp[i] = items[(first + i) % items.length];
        }
        items = temp;
        first = 0;
    }

    @SuppressWarnings("unchecked")
    private void realign(){
        temp = (E[]) new Object[size];
        for(int i = 0; i < size; i++){
            temp[i] = items[(first + i) % items.length];
        }
        items = temp;
        first = 0;
    }

    public int size(){
        return size;
    }

    public boolean isEmpty(){
        if(size == 0){
            return true;
        }
        return false;
    }

    @Override
    public Iterator<E> iterator() {
        Iterator<E> it = new Iterator<E>(){
            private int currentIndex = first;

            @Override
            public boolean hasNext() {
                return currentIndex < size && items[currentIndex] != null;
            }

            @Override
            public E next() {
                return items[currentIndex++];
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
        return it;
    }

    public String toString(){
        String str = "[";
        for(E e : items){
            str += e + ",";
        }
        str += "]";
        return str;
    }
}

РЕДАКТИРОВАТЬ: Мой вопрос заключается в том, как я могу исправить метод hasNext для моего Iterator. При итерации он будет идти только в конец списка, а не кружиться на переднем плане.

Класс Deque20 — это просто задание. Я должен написать свой собственный класс, который ведет себя как встроенный ArrayDeque.


person Ryan Bautista    schedule 21.05.2016    source источник
comment
Каков ваш вопрос, конкретно?   -  person Sotirios Delimanolis    schedule 21.05.2016
comment
как переопределить итератор на круговом массиве. В частности, hasNext   -  person Ryan Bautista    schedule 21.05.2016
comment
(Пожалуйста, отредактируйте это в своем вопросе.) Что не так с вашим текущим решением?   -  person Sotirios Delimanolis    schedule 21.05.2016
comment
Итак, имеет ли это фиксированный размер?   -  person ChiefTwoPencils    schedule 21.05.2016
comment
Метод hasNext не работает, и размер удваивается при достижении емкости   -  person Ryan Bautista    schedule 21.05.2016
comment
Можно конкретнее по вашему вопросу? Например, что вы пытаетесь сделать и в чем проблема? Кроме того, что на самом деле делает ваш класс Dequeue20? Это очередь или какой-то особый класс?   -  person Bijay Regmi    schedule 21.05.2016


Ответы (2)


Вам может потребоваться инициализировать currentIndex в конструкторе во внутреннем классе итератора, а также установить для currentIndex значение 0, когда размер превышен (при условии, что hasNext всегда будет вызываться перед next, иначе следующий должен иметь то же самое.), как в:

        public Iterator() {
            // init first position - assuming first element is always available somewhere in the array.
            for (int i = 0;i<items.length;i++) {
                if (items[i] == first) {
                    currentIndex = i;
                    break;
                }
            }
        }
    @Override
    public boolean hasNext() {
        if (currentIndex >= size()) {
            currentIndex = 0;
        }
        return  items[currentIndex] != null;
    }

Если есть вызовы next() без hasNext():

 public E next() {
            if (currentIndex >= size()) {
                currentIndex = 0;
            }
            return items[currentIndex++];
        }
person Rajeev Sampath    schedule 21.05.2016
comment
Сработало спасибо! также мне не нужен конструктор, я только использовал оператор if, чтобы проверить, прошел ли он через, и он работал нормально. - person Ryan Bautista; 21.05.2016

Я бы использовал currentOffset из first:

@Override
public Iterator<E> iterator() {
    return new Iterator<E>() {
        private int currentOffset = 0;

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

        @Override
        public E next() {
            E n = items[(first + currentOffset) % items.length];
            currentOffset += 1;
            return n;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    };
}

Кроме того, я предлагаю вам переименовать ваш метод doubleSize() в doubleCapacity(), так как вы фактически удваиваете емкость без внесения каких-либо изменений в размер очереди. В идеале вам следует подумать об обработке SimultaneousModificationException, в которой вы обнаружите изменения в двухсторонней очереди во время итерации.

person Kedar Mhaswade    schedule 21.05.2016