迭代器堆栈hasNext()没有返回true

时间:2015-01-09 14:37:34

标签: java arrays object interface iterator

我试图迭代一个Object数组。使用next()方法是有效的,所以我猜测我的迭代器类和构造函数正在工作。

由于某些原因,当hasNext()方法运行时,我没有得到任何输出。

        Iterator it = hej.iterator();
    Object j = it.next();
    System.out.println(j);


    while(it.hasNext()){
        Object i = it.next();
        System.out.println(i + " ");
    }

" hej"是我的Object数组。

我的下一个()代码;和hasNext()方法如下:

public class StackIterator implements Iterator<Object>{

// fields
private int element = 0;
private final Object[] elements;
private final int max;

// constructor

public StackIterator(Object[] values, int maxIndex) {
    elements = values;
    max = maxIndex;
}

// methods
public boolean hasNext() {
    return element < max;
}

public Object next() {
    return elements[element++];
}       

}

构造Object Array和Object Array的文件取决于接口:

public interface Stack {
int size();
boolean isEmpty();
void push(Object element);
Object pop();

Object peek();

Iterator<Object> iterator();

}

然后在另一个文件中解释这些方法:

public class StackExample implements Stack {

// fields
int length = 0;
Object[] arr;

// constructor
public StackExample() {arr = new Object[length];}


// method returns size of object array
public int size() {
    return arr.length;

}

// method checks if object is empty
public boolean isEmpty() {
    boolean result = false;
    if (arr.length == 0){
        result = true;

    }
    return result;
}

// method for push
public void push(Object element) {
    newBiggerObj();
    arr[0] = element;
}

// returns the first object of the stack
public Object pop() {
    Object[] temp = new Object[arr.length-1];
    Object first = arr[0];
    for (int i = 0; i<arr.length-1; i++){
        temp[i] = arr[i+1];
    }arr = temp;
    return first;
}

// returns the object on top of stack
public Object peek() {
if (isEmpty()){
    try{
        throw new Exception("Stack empty, can't peek!");
    }
    catch(Exception e){
        return e.getMessage();
    }
}

else {
    Object first = arr[0];
    return first;
}

}

// method for push method
private void newBiggerObj(){
    Object[] temp = new Object[arr.length+1];
    for (int i = 0; i<arr.length; i++){
        temp[i+1] = arr[i];
    }
    arr = temp;
}

public String toString(){
    String str = "";
    for (int i = 0; i < arr.length; i++){
        str = str + arr[i] + " , ";
    }return str;
}

public Iterator<Object> iterator() {
    return new StackIterator(arr, length);
}

}

困扰我的是Iterator方法本身返回了Stack Iterator类的实例。我在上面发布的。所以我真正的问题似乎是我的字段没有被赋予任何价值,因为我不是自己在构造函数中给出任何值。

我测试所有这些的主要方法如下:

public class Teststack {
public static void main(String[] args){
    // new instane of class StackExample
    StackExample hej = new StackExample();

    // test for the different methods
    System.out.println(hej.isEmpty());
    System.out.println(hej.size());
    hej.push(4);
    hej.push("hej");
    hej.push(6);
    hej.push(5);
    System.out.println(hej.size());
    System.out.println(hej.peek());
    System.out.println(hej.pop());
    System.out.println(hej.toString());
    System.out.println(hej.isEmpty());


    System.out.println("Testing Iterator: ");
    // test for iterator
    Iterator it = hej.iterator();
    Object j = it.next();
    System.out.println(j);


    while(it.hasNext()){
        Object i = it.next();
        System.out.println(i + " ");
    }
}

}

5 个答案:

答案 0 :(得分:1)

StackExample课程中,我不会看到在推送或弹出元素时更新的length变量。因此,length将始终为0,并且对it.hasNext()的调用将始终返回false。

您不需要将长度作为单独的参数传递。您可以在StackIterator构造函数中找到数组的长度并使用它。

另请注意,由于您在每次推送和弹出时都创建了一个新数组,StackExample#iterator()返回的迭代器在每次推送/弹出后都会变得陈旧,因为它可以在旧的副本/状态下工作堆栈。

答案 1 :(得分:0)

几个问题:

  • 在创建迭代器后调用Object j = it.next();,然后检查hasNext。您正在递增元素索引。因此,如果您只有一个元素,则不会进入while循环。此外,如果您的自定义数据结构为空,即数组没有元素,那么您很容易出现ArrayIndexOutOfBoundException。
  • 您将始终迭代并打印n-1个元素,而不是n个元素。
  • 一旦你迭代,你的指针将始终指向最后一个元素,永远不会被重置。所以下次你不能迭代你的元素。它是一次迭代器。

答案 2 :(得分:0)

尽量不要打电话 对象j = it.next()语句,但只是循环。看起来你有一个只有1个元素的数组。

答案 3 :(得分:0)

问题在于:

public Iterator<Object> iterator() {
    return new StackIterator(arr, length);
}

length字段永远不会更改,因此其值始终为0。您可以将代码更改为:

public Iterator<Object> iterator() {
    return new StackIterator(arr, arr.length);
}

此外,在从迭代器中检索元素之前,应始终调用it.hasNext。你这样做的事实:

Iterator it = hej.iterator();
Object j = it.next();

工作只是纯粹的运气。


除此之外,我可以感觉到你的堆栈实现设计不好。以下是一些改进代码的提示:

  • 应使用不同于0的默认大小初始化内部数组。 10(如java.util.ArrayList实施中所述)。
  • 添加(push)或从堆栈中删除(pop)元素时,应避免创建新数组。除此之外,您应该使用length字段来控制stack中的元素数量。
  • 新尺寸的值应基于另一个公式,而不是array.length + 1。例如,尝试使用int newSize = array.length / 2 * 3;
  • 之类的内容
  • 仅在必要时调整内部数组的大小。调用push时,仅在您需要增加数组大小时才执行此操作。在调用pop时,如果数组的当前长度(array.length)远远超过您班级length字段的值,请执行此操作。
  • 永远不要忘记在lengthpush方法上更新pop的值。

答案 4 :(得分:0)

此代码存在许多问题:

  • StackIterator构造函数中,maxIndex没有边界检查。呼叫者可以传入大于values.length,小于0等的数字
  • next方法中,无法直接或通过调用hasNext()来检查结束条件。来电者可以继续致电next()并查看max以外的元素,甚至可以获得ArrayIndexOutOfBoundsException,这时他们应该获得NoSuchElementException
  • 当推送或弹出元素时,Stack类永远不会递增或递减其length字段。
  • Stack类与数组分开跟踪length,即使它总是在每次推送或弹出时调整数组大小,但Java数组已经知道它们的大小。 (但请参阅下一个项目。)
  • Stack类在每次推送或弹出时调整数组大小,效率非常低。通常,这样的类只在必要时调整数组大小,允许“松弛”空间,以提供分摊的常量时间性能(请参阅ArrayList)。但是,如果执行此操作,则必须null弹出项目以避免无意识的对象保留。
  • Stack在数组的开头添加和删除元素。这是非常低效的,因为这意味着必须在每次推送或弹出时进行O(n)重新洗牌。
  • peek()方法考虑了Stack可能为空的可能性,但pop()方法没有。空pop()上的Stack会抛出ArrayIndexOutOfBoundsException
  • Stack不是通用类。它持有ObjectStack的用户必须转换peek()pop()的返回值,并且它不是类型安全的。在您的示例中,您显示的堆栈是StringInteger的异构混合。这是一种非常Java的方式,虽然它不一定是错的,但您应该考虑参数化Stack