如何实现相当于 Java 中的嵌套循环的迭代器
How to implement an Iterator that will be an equivalent of a nested loop in Java
我在 Python 中有以下生成器:
def iterator(min,max,step,min2,max2,step2):
for x in range(min,max,step):
for y in range(min2, max2, step2):
result = foo(x, y)
yield result
我想在 Java 中实现一个 Iterator
,它的行为有点像以前的生成器。我试过使用两个内部迭代器,但它不起作用。
我该如何解决?
public class Generator implements Iterator<Integer> {
private Iterator<Integer> xIterator;
private Iterator<Integer> yIterator;
public Generator(int max1, int max2, int min1, int min2, int step1, int step2) {
xIterator = range(min1, max1, step1).iterator();
yIterator = range(min2, max2, step2).iterator();
}
@Override
public Integer next() {
while (xIterator.hasNext()) {
xval = xIterator.next()
while(yIterator.hasNext()) {
yval = yIterator.next()
return foo(xval, yval)
}
}
}
public static int[] range(int min, int max, int step) {
return IntStream.range(min, max / step + 1).map(x -> x * step).toArray();
}
}
在 Python 中,在 yield 语句之后,对 Generator 的下一次调用在该 yield 语句之后继续 - 这是在内循环中。
在 Java 中,在 return 之后,对 next() 的下一次调用将在 while 循环之外继续,所以它做的第一件事总是检查 xIterator.hasNext (),如果为真,则递增 xval。我认为这可能是主要的误解。
范围函数似乎也没有做它应该做的事情。也许检查 Java: Equivalent of Python's range(int, int)? - 那里的一些答案也包括 step 参数。
您发布的代码也无法编译,原因如下:
- next() 并不总是 return 一个值。如果不存在(更多)元素,它应该抛出 NoSuchElementException。
- hasNext() 未实现,使用这种方法实际上可能非常困难。
- xval 和 yval 未声明。
Java 中的 迭代器 是一个特殊的对象,迭代的平均值,它允许按顺序检索元素来自特定来源的一个。
创建自定义迭代器时有两种方法必须实现:hasNext()
(returns true
如果下一个元素存在)和next()
(检索下一个元素)。
您没有为 class 提供 hasNext()
的实现,否则您的代码将无法编译。
并且next()
方法有一个逻辑缺陷,它不会编译,因为你没有提供return语句或throws子句,当控制无法进入循环时将被执行。但更重要的是,您不需要此方法中的循环和任何条件逻辑,它必须被通常必须在 next()
之前调用的 hasNext()
覆盖。如果客户端代码不遵守它,方法 next()
可能会产生异常。您可以在 next()
方法的最开头添加 if (hasNext())
以针对您的自定义消息发出特定异常。
方法 iterator()
可通过数组访问。您可以将它与实现 Iterable
接口的 classes 一起使用,例如集合,您还可以在流上调用 iterator()
。所以你可以像这样重新实现你的方法range()
:
IntStream.iterate(min, i -> i < max, i -> i + step).iterator();
这就是修复迭代器的方法:
public class Generator implements Iterator<Integer> {
private final Iterator<Integer> xIterator;
private final Iterator<Integer> yIterator;
public Generator(int minX, int minY, int maxX, int maxY, int stepX, int stepY) {
this.xIterator = range(minX, maxX, stepX);
this.yIterator = range(minY, maxY, stepY);
}
public static Iterator<Integer> range(int min, int max, int step) {
return IntStream.iterate(min, i -> i < max, i -> i + step).iterator();
}
@Override
public boolean hasNext() {
return xIterator.hasNext() && yIterator.hasNext();
}
@Override
public Integer next() {
return foo(xIterator.next(), yIterator.next());
}
}
但我的建议是更注重效率和简洁而不是简洁。因为迭代器产生的所有值都可以很容易地动态计算,所以不需要预先分配它们来占用内存。
相反,您可以维护两个变量 curX
和 curY
。这个解决方案很简单,而且还可以更好地控制迭代器,因为您没有委托迭代过程。因此,您可以实现 reset()
功能(以前的解决方案是不可能的,Iterator
在到达数据源末尾时变得无用)。
public class Generator implements Iterator<Integer> {
private final int minX;
private final int minY;
private final int maxX;
private final int maxY;
private final int stepX;
private final int stepY;
private int curX;
private int curY;
public Generator(int minX, int minY, int maxX, int maxY, int stepX, int stepY) {
this.minX = minX;
this.minY = minY;
this.maxX = maxX;
this.maxY = maxY;
this.stepX = stepX;
this.stepY = stepY;
this.curX = minX;
this.curY = minY;
}
@Override
public boolean hasNext() {
return curX < maxX && curY < maxY;
}
@Override
public Integer next() {
int result = foo(curX, curY);
curX += stepX;
curY += stepY;
return result;
}
public void reset() { // reset the iterator to the initial coordinates
this.curX = minX;
this.curY = minY;
}
}
我在 Python 中有以下生成器:
def iterator(min,max,step,min2,max2,step2):
for x in range(min,max,step):
for y in range(min2, max2, step2):
result = foo(x, y)
yield result
我想在 Java 中实现一个 Iterator
,它的行为有点像以前的生成器。我试过使用两个内部迭代器,但它不起作用。
我该如何解决?
public class Generator implements Iterator<Integer> {
private Iterator<Integer> xIterator;
private Iterator<Integer> yIterator;
public Generator(int max1, int max2, int min1, int min2, int step1, int step2) {
xIterator = range(min1, max1, step1).iterator();
yIterator = range(min2, max2, step2).iterator();
}
@Override
public Integer next() {
while (xIterator.hasNext()) {
xval = xIterator.next()
while(yIterator.hasNext()) {
yval = yIterator.next()
return foo(xval, yval)
}
}
}
public static int[] range(int min, int max, int step) {
return IntStream.range(min, max / step + 1).map(x -> x * step).toArray();
}
}
在 Python 中,在 yield 语句之后,对 Generator 的下一次调用在该 yield 语句之后继续 - 这是在内循环中。
在 Java 中,在 return 之后,对 next() 的下一次调用将在 while 循环之外继续,所以它做的第一件事总是检查 xIterator.hasNext (),如果为真,则递增 xval。我认为这可能是主要的误解。
范围函数似乎也没有做它应该做的事情。也许检查 Java: Equivalent of Python's range(int, int)? - 那里的一些答案也包括 step 参数。
您发布的代码也无法编译,原因如下:
- next() 并不总是 return 一个值。如果不存在(更多)元素,它应该抛出 NoSuchElementException。
- hasNext() 未实现,使用这种方法实际上可能非常困难。
- xval 和 yval 未声明。
Java 中的 迭代器 是一个特殊的对象,迭代的平均值,它允许按顺序检索元素来自特定来源的一个。
创建自定义迭代器时有两种方法必须实现:hasNext()
(returns true
如果下一个元素存在)和next()
(检索下一个元素)。
您没有为 class 提供 hasNext()
的实现,否则您的代码将无法编译。
并且next()
方法有一个逻辑缺陷,它不会编译,因为你没有提供return语句或throws子句,当控制无法进入循环时将被执行。但更重要的是,您不需要此方法中的循环和任何条件逻辑,它必须被通常必须在 next()
之前调用的 hasNext()
覆盖。如果客户端代码不遵守它,方法 next()
可能会产生异常。您可以在 next()
方法的最开头添加 if (hasNext())
以针对您的自定义消息发出特定异常。
方法 iterator()
可通过数组访问。您可以将它与实现 Iterable
接口的 classes 一起使用,例如集合,您还可以在流上调用 iterator()
。所以你可以像这样重新实现你的方法range()
:
IntStream.iterate(min, i -> i < max, i -> i + step).iterator();
这就是修复迭代器的方法:
public class Generator implements Iterator<Integer> {
private final Iterator<Integer> xIterator;
private final Iterator<Integer> yIterator;
public Generator(int minX, int minY, int maxX, int maxY, int stepX, int stepY) {
this.xIterator = range(minX, maxX, stepX);
this.yIterator = range(minY, maxY, stepY);
}
public static Iterator<Integer> range(int min, int max, int step) {
return IntStream.iterate(min, i -> i < max, i -> i + step).iterator();
}
@Override
public boolean hasNext() {
return xIterator.hasNext() && yIterator.hasNext();
}
@Override
public Integer next() {
return foo(xIterator.next(), yIterator.next());
}
}
但我的建议是更注重效率和简洁而不是简洁。因为迭代器产生的所有值都可以很容易地动态计算,所以不需要预先分配它们来占用内存。
相反,您可以维护两个变量 curX
和 curY
。这个解决方案很简单,而且还可以更好地控制迭代器,因为您没有委托迭代过程。因此,您可以实现 reset()
功能(以前的解决方案是不可能的,Iterator
在到达数据源末尾时变得无用)。
public class Generator implements Iterator<Integer> {
private final int minX;
private final int minY;
private final int maxX;
private final int maxY;
private final int stepX;
private final int stepY;
private int curX;
private int curY;
public Generator(int minX, int minY, int maxX, int maxY, int stepX, int stepY) {
this.minX = minX;
this.minY = minY;
this.maxX = maxX;
this.maxY = maxY;
this.stepX = stepX;
this.stepY = stepY;
this.curX = minX;
this.curY = minY;
}
@Override
public boolean hasNext() {
return curX < maxX && curY < maxY;
}
@Override
public Integer next() {
int result = foo(curX, curY);
curX += stepX;
curY += stepY;
return result;
}
public void reset() { // reset the iterator to the initial coordinates
this.curX = minX;
this.curY = minY;
}
}