迭代器堆栈 hasNext() 不返回 true
Iterator stack hasNext() not returning true
我正在尝试遍历对象数组。使用 next() 方法有效,所以我猜测我的迭代器 class 和构造函数正在工作。
由于某些原因,我在 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" 是我的对象数组。
我的 next() 代码;和 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 方法在其自身内返回 class 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 + " ");
}
}
}
几个问题:
- 您在创建迭代器后调用
Object j = it.next();
,然后检查 hasNext。您正在增加元素索引。因此,如果您只有一个元素,则不会进入 while 循环。此外,如果您的自定义数据结构为空,即数组没有元素,那么您很容易出现 ArrayIndexOutOfBoundException。
- 您将始终迭代并打印 n-1 个元素而不是 n 个元素。
- 迭代后,您的指针将始终指向最后一个元素并且永远不会重置。所以下次你将无法迭代你的元素。它是一次性迭代器。
尽量不要打电话
Object j = it.next() 语句,只是while循环。似乎你有一个只有 1 个元素的数组。
在您的 StackExample
class 中,当元素被压入或弹出时,我没有看到 length
变量被更新。因此,length
将始终为 0,对 it.hasNext()
的调用将始终 return false。
您不需要将长度作为单独的参数传递。您可以在 StackIterator
构造函数中找到数组的长度并使用它。
另请注意,由于您在每次推送和弹出时都创建了一个新数组,因此由 StackExample#iterator()
编辑的迭代器 return 将在每次 push/pop 之后变得陈旧,因为它可以工作在堆栈的旧 copy/state 上。
问题在这里:
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
)远大于 class 的 length
字段的值,则执行此操作。
- 永远不要忘记在
push
和 pop
方法上更新 length
的值。
此代码存在许多问题:
- 在
StackIterator
构造函数中,maxIndex
没有边界检查。调用者可以传入大于 values.length
、小于 0 等的数字
- 在
next
方法中,没有直接或通过调用 hasNext()
检查结束条件。呼叫者可以继续呼叫 next()
并查看 max
之外的元素,甚至在他们应该获得 NoSuchElementException
. 时获得 ArrayIndexOutOfBoundsException
- 当元素被压入或弹出时,
Stack
class 从不增加或减少其 length
字段。
Stack
class 将 length
与数组分开跟踪,即使它总是在每次推送或弹出时调整数组的大小,但 Java 数组已经知道他们的大小。 (但请看下一项。)
Stack
class 在每次推送或弹出时调整数组的大小,这是非常低效的。通常像这样的 classes 只在必要时调整数组的大小,允许 'slack' space,以提供摊销的常数时间性能(请参阅 ArrayList)。但是,如果您这样做,则有必要 null
弹出的项目以避免意外保留对象。
Stack
在数组的开头添加和删除元素。这是非常低效的,因为这意味着必须在 每次 推送或弹出时进行 O(n) 重新洗牌。
peek()
方法考虑到了Stack
可能为空的可能性,而pop()
方法则没有。空 Stack
上的 pop()
将抛出 ArrayIndexOutOfBoundsException
.
Stack
不是通用的 class。它持有 Object
。 Stack
的用户必须从 peek()
或 pop()
转换为 return 值,而且它不是类型安全的。在您的示例中,您显示的堆栈是 String
和 Integer
的异质混合物。这是非常 Java 1.2 的处理方式,虽然不一定是错误的,但您应该考虑参数化 Stack
.
我正在尝试遍历对象数组。使用 next() 方法有效,所以我猜测我的迭代器 class 和构造函数正在工作。
由于某些原因,我在 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" 是我的对象数组。
我的 next() 代码;和 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 方法在其自身内返回 class 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 + " ");
}
}
}
几个问题:
- 您在创建迭代器后调用
Object j = it.next();
,然后检查 hasNext。您正在增加元素索引。因此,如果您只有一个元素,则不会进入 while 循环。此外,如果您的自定义数据结构为空,即数组没有元素,那么您很容易出现 ArrayIndexOutOfBoundException。 - 您将始终迭代并打印 n-1 个元素而不是 n 个元素。
- 迭代后,您的指针将始终指向最后一个元素并且永远不会重置。所以下次你将无法迭代你的元素。它是一次性迭代器。
尽量不要打电话 Object j = it.next() 语句,只是while循环。似乎你有一个只有 1 个元素的数组。
在您的 StackExample
class 中,当元素被压入或弹出时,我没有看到 length
变量被更新。因此,length
将始终为 0,对 it.hasNext()
的调用将始终 return false。
您不需要将长度作为单独的参数传递。您可以在 StackIterator
构造函数中找到数组的长度并使用它。
另请注意,由于您在每次推送和弹出时都创建了一个新数组,因此由 StackExample#iterator()
编辑的迭代器 return 将在每次 push/pop 之后变得陈旧,因为它可以工作在堆栈的旧 copy/state 上。
问题在这里:
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
)远大于 class 的length
字段的值,则执行此操作。 - 永远不要忘记在
push
和pop
方法上更新length
的值。
此代码存在许多问题:
- 在
StackIterator
构造函数中,maxIndex
没有边界检查。调用者可以传入大于values.length
、小于 0 等的数字 - 在
next
方法中,没有直接或通过调用hasNext()
检查结束条件。呼叫者可以继续呼叫next()
并查看max
之外的元素,甚至在他们应该获得NoSuchElementException
. 时获得 - 当元素被压入或弹出时,
Stack
class 从不增加或减少其length
字段。 Stack
class 将length
与数组分开跟踪,即使它总是在每次推送或弹出时调整数组的大小,但 Java 数组已经知道他们的大小。 (但请看下一项。)Stack
class 在每次推送或弹出时调整数组的大小,这是非常低效的。通常像这样的 classes 只在必要时调整数组的大小,允许 'slack' space,以提供摊销的常数时间性能(请参阅 ArrayList)。但是,如果您这样做,则有必要null
弹出的项目以避免意外保留对象。Stack
在数组的开头添加和删除元素。这是非常低效的,因为这意味着必须在 每次 推送或弹出时进行 O(n) 重新洗牌。peek()
方法考虑到了Stack
可能为空的可能性,而pop()
方法则没有。空Stack
上的pop()
将抛出ArrayIndexOutOfBoundsException
.Stack
不是通用的 class。它持有Object
。Stack
的用户必须从peek()
或pop()
转换为 return 值,而且它不是类型安全的。在您的示例中,您显示的堆栈是String
和Integer
的异质混合物。这是非常 Java 1.2 的处理方式,虽然不一定是错误的,但您应该考虑参数化Stack
.
ArrayIndexOutOfBoundsException