2014-03-22 3 views
0

Я должен реализовать класс 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; 
    } 

} 

и в Testcode:

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 + " "); 
    } 

    } 


} 

Я не знаю, где я ошибся.

ответ

3

Ошибка в том, что вы не инициализируете 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.

EDIT:

В отредактированной сообщению, вы должны изменить метод 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; 
    } 

} 
+0

Спасибо Я отредактировал OP. Взгляни, пожалуйста. Еще раз спасибо. – Yoda

+0

Спасибо, я снова отредактировал код, как вы сказали. Но, к сожалению, результат такой же, как и в исходном сообщении. Взгляни, пожалуйста. О, отредактирован op – Yoda

+0

@Yoda Отредактирован мой ответ. –

2

Вы начинаете с одной фундаментальной ошибки: aПредполагается, чтоможет выдавать бесконечное количество Iterator, но вы можете только оформить его.

Каждый 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(); 
} 

И нет, вам не нужно объявлять, что метод выдает это исключение, так как он является непроверенным исключение. См. Javadoc для RuntimeException.

+0

Как я должен установить 'start'' end' и 'step' для итератора. Я не знаю, как получить к нему доступ методом 'by()'. Пример 'в (1, 10) .by (-1)' 'start' должен быть установлен в 1,' end' до 10 и 'step' tp -1. – Yoda

+1

Хммм ... Это требование вашего упражнения?Вы не должны изменять поведение итератора во время его работы ... – fge

+0

Да, это к сожалению. В упражнении учитель написал: // W trakcie iteracji można zmieniac krok, что означает, что при повторении вы можете изменить шаг. Но это очень плохой учитель (не мой учитель). – Yoda

Смежные вопросы