可逆循环

时间:2010-11-03 02:21:43

标签: java concept foreach

我一直在尝试一款我想要制作的游戏。我发现除了for循环外,我有两种方法是相同的,这与前者相反。

我试图这样做,所以我可以使用相同的代码向前或向后。我最终得到了:

for (int i = start; i != (finish + 1 * ((start < finish) ? 1 : -1)); i += 1 * ((start < finish) ? 1 : -1))

A)B)我想与大家分享这个概念。

B)我很好奇这种循环的效率。我知道它在计算目标数量和访问时的影响因素,但我不知道如何测试它。

C)当我在它的时候,我找到了一条线,它可以交换两个变量而不使用临时变量。这需要一点时间来阅读,但这比使用临时更好(代码明智)吗? (下面主要的第3行)

我已经测试了它的功能,它按预期运行。如果第二个数字大于第一个数字,则计数。如果没有,它会倒计时。我的测试代码是:

// A generic loop that can go up or down
import java.io.*;

public class reversable
{
  public static int start = 1;
  public static int finish = 10;

   public static void main(String[] args)
  {
     for (int i = start; i != (finish + 1 * ((start < finish) ? 1 : -1)); i += 1 * ((start < finish) ? 1 : -1))
     {
        System.out.println("i = " + i);
     }
     finish = (start + finish) - (start = finish);  
System.out.println("Finish = " + finish);
System.out.println("Start = " + start);
     for (int i = start; i != (finish + 1 * ((start < finish) ? 1 : -1)); i += 1 * ((start < finish) ? 1 : -1))
     {
        System.out.println("i = " + i);
     }
     finish = 10;
     for (int i = start; i != (finish + 1 * ((start < finish) ? 1 : -1)); i += 1 * ((start < finish) ? 1 : -1))
     {
        System.out.println("i = " + i);
     }
  }
}

根据评论,这是否可以接受:

public static void reversable (int i, int j)
{
  if (i > j) int inc = -1;  // Count down
  else       int inc = 1;  // Count up
  j += inc;
  for (i; i != j; i += inc)
  {
    dostuff();
    morestuff();
    mostuff();
  }
}

4 个答案:

答案 0 :(得分:15)

你应该努力编写可读代码,而不是代码在一行中做很多事情或者有花哨的技巧。

如果我和你一起开展一个项目,我可能想在你第一次读到for循环之后扼杀你,也就是说如果我的脑袋没有爆炸试图先了解它。同意在作业中进行分配。

答案 1 :(得分:10)

如果我在生产中看到这段代码,我会立即将它重构为更具可读性的东西,这可能就像你开始时的那样。

考虑一下您希望减少代码重复的原因。这是为了使您的代码更易于维护。你觉得你做到了吗?

  

当我在它的时候,我找到了一条线,它可以交换两个变量而不使用临时变量。这需要一点时间来阅读,但这比使用temp更好(代码明智)吗?

这仅适用于数字类型,所以我觉得它不是那么有用。对于不了解技巧的人来说,你的代码可读性较差,从而减慢了代码的维护速度。我不认为值得节省一个临时变量。

答案 2 :(得分:6)

你不是想成为一块砖,但我认为你试着写:

public static void doAction(int i) {
    System.out.println("i = " + i);
}

public static void loopValues(int i, int j) {
    if (i > j) while (i >= j) doAction(i--);
    else       while (i <= j) doAction(i++);;
}

public static void main(String[] args) {
    int start = 1, finish = 10;
    loopValues(start, finish);
    loopValues(finish, start);
}

您有2个循环的原因是效率和案例可读性。比较是昂贵的操作,你通常不想添加额外的比较循环只是为了改变它的正常过程。

答案 3 :(得分:0)

事实上,代码很难遵循......但对批评者来说已经足够了。当有人要求只有循环不同的可重用方法时,唯一想到的是Iteratoriterator pattern正是您对此可重用案例所需要的。如果将迭代器包装在Iterable接口中,则可以在for块内轻松使用它。示例:

public class IntegerRange implements Iterable<Integer> {
   private boolean reverse;
   private int start;
   private int end;

   public IntegerRange(int start, int end) {
      this.reverse = (start > end);
      this.start = start;
      this.end = end;
   }

   @Override
   public Iterator<Integer> iterator() {
      return new IntegerIterator();
   }


   private class IntegerIterator implements Iterator<Integer> {

      private int current;

      private IntegerIterator() {
         current = start;
      }

      @Override
      public boolean hasNext() {
         if (reverse) {
            return (end <= current);
         } else {
            return (current <= end);
         }
      }

      @Override
      public Integer next() {
         if (!hasNext()) {
            throw new NoSuchElementException();
         }
         if (reverse) {
            return current--;
         } else {
            return current++;
         }
      }

      @Override
      public void remove() {
         throw new UnsupportedOperationException("Cannot remove from this iterator");
      }
   }

}

然后使用并重用你的迭代器......

static public void main(String...args) {
   doStuff(new IntegerRange(1, 10));
   doStuff(new IntegerRange(10, 1));
}

static private void doStuff(IntegerRange range) {
   for (int i : range) {
      System.out.println("i = " + i);
   }
} 

代码现在更易读。