迭代器返回错误的整数值

时间:2014-03-22 12:54:18

标签: java iterator integer iterable

我必须实现类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 + " ");
    }

  }


}

我不知道我错在哪里。

2 个答案:

答案 0 :(得分:3)

错误在于您没有初始化val,因此它将从0开始(默认值)。

在您的第二个示例中,您将return val += step;val = 0step = 2,因此它将从2开始并从那里继续。

在您的第三个示例a = 10b = 1step = -1val = 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()方法,以便在需要时将ab反转:

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;
    }

}

答案 1 :(得分:2)

您首先犯了一个基本错误:Iterable应该能够发出无限多个Iterator,但您只能发出一个。{/ p>

每个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。