迭代器返回错误的整数值
Posted
技术标签:
【中文标题】迭代器返回错误的整数值【英文标题】:Iterator returns wrong integer values 【发布时间】:2014-04-29 22:45:45 【问题描述】:我必须实现类Incrementer
,它假设实现Iterable
。
输出应该是:
1 2 3 4 5 6 7 8 9 10
1 3 5 7 9
10 9 8 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2 1
1 2 3 4 6 8 10
1 2 3 4 5 6 7 8 6 4 2
10 9 8 7 6 5 6 7 8 9 10
我明白了:
2 3 4 5 6 7 8 9 10
3 5 7 9 11
9 8 7 6 5 4 3 2 1
2 3 4 6 8 10
2 3 4 5 6 7 8
9 8 7 6 5 6 7 8 9 10
我的Incrementer
班级看起来像这样:
package in;
import java.util.Iterator;
public class Incrementer implements Iterable<Integer>
int val, step, a, b;
private Incrementer(int a, int b, int step)
this.step = step;
this.a = a;
this.b = b;
if (step > 0)
val = a;
else
val = b;
@Override
public Iterator<Integer> iterator()
return new Iterator<Integer>()
@Override
public boolean hasNext()
if (step < 0 && val > a)
return true;
else if (step > 0 && val < b)
return true;
return false;
@Override
public Integer next()
return val += step;
@Override
public void remove()
;
public static Incrementer in(int a, int b)
///tu zmieniamy tresc dla ostatniego przypadku
if (a < b)
return new Incrementer(a, b, 1);
else
return new Incrementer(b, a, -1);
public Incrementer by(int step)
this.step = step;
if (this.step < 0 && this.a < this.b || this.step > 0 && this.a > this.b)
int tmp = this.a;
this.a = this.b;
this.b = tmp;
return this;
和测试代码:
package in;
import static in.Incrementer.*;
public class Test
public static void main(String[] args)
for(int k : in(1, 10)) System.out.print(k + " ");
System.out.println();
for(int k : in(1, 10).by(2)) System.out.print(k + " ");
System.out.println();
for(int k : in(10, 1)) System.out.print(k + " ");
System.out.println();
for(int k : in(1, 10).by(-1)) System.out.print(k + " ");
System.out.println();
Incrementer inc;
for (int i : inc = in(1,10) )
if (i == 4) inc.by(2);
System.out.print(i + " ");
System.out.println();
for (int i : inc = in(1,10) )
if (i == 8) inc.by(-2);
System.out.print(i + " ");
System.out.println();
for(int k : inc = in(10, 1))
if (k == 5) inc.by(1);
System.out.print(k + " ");
我不知道我在哪里做错了。
【问题讨论】:
【参考方案1】:错误是你没有初始化val
,所以会从0
(默认值)开始。
在您的第二个示例中,您将使用return val += step;
、val = 0
和 step = 2
,因此它将从 2
开始并从那里继续。
在您的第三个示例中,a = 10
、b = 1
、step = -1
和 val = 0
,因此您不会进入
if (step < 0 && val > a)
因为val < a
,而你不会进入
else if (step > 0 && val < b)
因为step < 0
。
编辑:
在编辑后的帖子中,你应该修改next()
方法返回val
,并且只在后面增加它:
@Override
public Integer next()
int ret = val;
val += step;
return val;
你还应该修改hasNext()
中的条件:
@Override
public boolean hasNext()
if (step < 0 && val >= a)
return true;
else if (step > 0 && val <= b)
return true;
return false;
为了使您进行第四次测试工作,您必须将by()
方法更改为反转a
和b
(如果需要):
public Incrementer by(int step)
if ((this.step<0)!=(step<0) && this.val==this.a)
this.val = this.b;
else if ((this.step<0)!=(step<0) && this.val==this.b)
this.val = this.a;
else if (this.val!=this.a && this.val!=this.b)
this.val -= this.step;
this.val += step;
this.step = step;
return this;
你也可以测试反例:
for(int k : in(10, 1).by(1)) System.out.print(k + " ");
完整代码如下:
public class Incrementer implements Iterable<Integer>
int val, step, a, b;
private Incrementer(int a, int b, int step)
this.step = step;
this.a = a;
this.b = b;
if (step > 0)
val = a;
else
val = b;
@Override
public Iterator<Integer> iterator()
return new Iterator<Integer>()
@Override
public boolean hasNext()
if (step < 0 && val >= a)
return true;
else if (step > 0 && val <= b)
return true;
return false;
@Override
public Integer next()
int ret = val;
val += step;
return ret;
@Override
public void remove()
;
public static Incrementer in(int a, int b)
///tu zmieniamy tresc dla ostatniego przypadku
if (a < b)
return new Incrementer(a, b, 1);
else
return new Incrementer(b, a, -1);
public Incrementer by(int step)
if ((this.step<0)!=(step<0) && this.val==this.a)
this.val = this.b;
else if ((this.step<0)!=(step<0) && this.val==this.b)
this.val = this.a;
else if (this.val!=this.a && this.val!=this.b)
this.val -= this.step;
this.val += step;
this.step = step;
return this;
【讨论】:
谢谢我编辑了 OP。请看一下。再次感谢您。 谢谢我再次编辑代码,就像你说的。但不幸的是,输出与原始帖子中发布的相同。请看一下。哦,操作已编辑 @Yoda 编辑了我的答案。【参考方案2】:你一开始就犯了一个根本性错误:Iterable
应该能够发出无限多个 Iterator
s,但你只能发出一个。
每个Iterator
都应该有足够的内部状态,以便能够迭代您的值集。
要同时解决这个问题和其他问题,请将iterator()
中的代码更改为此:
@Override
public Iterator<Integer> iterator()
return new Iterator<Integer>()
int val = a; // <-- HERE
并将您的 .next()
更改为:
public Integer next()
int ret = val;
val += step;
return ret;
并删除您的其他val
。
(另外,我建议您将 a
重命名为 start
和 b
重命名为 end
)
最后一句话:为了完全遵守Iterator
的合同,你的.remove()
应该这样做:
public void remove()
throw new UnsupportedOperationException();
不,您不需要声明该方法会引发此异常,因为它是一个未经检查的异常。请参阅 RuntimeException
的 javadoc。
【讨论】:
我应该如何将start
end
和step
设置为迭代器。我不知道如何通过方法by()
访问它。示例 in(1, 10).by(-1)
start
应设置为 1,end
应设置为 10,step
tp -1。
嗯...这是你锻炼的要求吗?您不应该能够在迭代器运行时修改它的行为...
是的,很不幸。在练习中老师写道:// W trakcie iteracji można zmieniac krok 这意味着在迭代时您可以更改步骤。但这是非常糟糕的老师(不是我的老师)。
哦,天哪...一位老师要求故意违约:/以上是关于迭代器返回错误的整数值的主要内容,如果未能解决你的问题,请参考以下文章
Medium | LeetCode 341. 扁平化嵌套列表迭代器 | 递归 | 栈