【问题标题】:Overriding Iterator in circular array在循环数组中覆盖迭代器
【发布时间】:2016-09-18 08:43:34
【问题描述】:

我正在编写自己的 Deque 类,我需要重写迭代器。

示例:假设数组是 [3,4,5,null,null,null,1,2],其中 1 是前面,5 是结尾。我需要能够使用迭代器从 1 开始并在 5 之后结束。

这是我的整个 Deque 类。我相信除了 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 方法。迭代时它只会转到列表的末尾,而不是绕到前面。

Deque20 类只是一个任务,我必须编写自己的类,其行为类似于内置的 ArrayDeque。

【问题讨论】:

  • 你的问题是什么,具体
  • 如何覆盖循环数组上的迭代器。特别是 hasNext
  • (请将其编辑到您的问题中。)您当前的解决方案有什么问题?
  • 那么,这有固定大小吗?
  • hasNext方法不起作用,达到容量时大小会加倍

标签: java arrays iterator deque circular-list


【解决方案1】:

您可能需要在迭代器内部类的构造函数中初始化 currentIndex,并在超过 size 时将 currentIndex 设置为 0(假设 hasNext 总是在 next 之前调用,否则 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;
    }

如果有没有 hasNext() 的 next() 调用:

 public E next() {
            if (currentIndex >= size()) {
                currentIndex = 0;
            }
            return items[currentIndex++];
        }

【讨论】:

  • 工作,谢谢!我也不需要构造函数,我只使用 if 语句来检查它是否超过了它并且工作正常。
【解决方案2】:

我会使用来自firstcurrentOffset

@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,您可以在其中检测到在迭代时对双端队列的更改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-10
    • 1970-01-01
    • 2014-06-08
    • 2019-03-10
    • 2014-06-21
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多