【问题标题】:Why java numbers aren't iterable为什么java数字不可迭代
【发布时间】:2011-05-02 15:22:57
【问题描述】:

我不能一直想知道为什么我不能写这样的东西:

for (int i : 3) {
  System.out.println(i);
}

打印出来:

0
1
2

我的意思是,3 可以自动装箱为Integer,也可以是Iterable
我知道,我选择了第一个元素为 0,但我认为这是常见的情况,并且它可以促进使用这种 ForEach 构造倒计时。

【问题讨论】:

  • 只需使用常规的 for 循环。 (for int i: n)... 不是 Java 习语,试图硬塞一些其他语言风格通常会给你带来麻烦
  • @Emil:“为什么 Java 数字不可迭代”?但让我换个说法:“为什么 Java 整数不可迭代,以便它们可以在 for each 循环中使用”。
  • 我认为这是对语言的一个非常明智的补充。是的,这将是一个新的习语,但可读性强(恕我直言),不易出错(例如,传统的 for 循环重复 i 3 次),并且可能会取代世界上近一半的 for 循环。如果我犯的每一个for (int j=0; j<LIMIT; ++i) 错误都能得到一分钱……

标签: java foreach primitive-types


【解决方案1】:

这有点愚蠢,但你可以这样写:

    for (int i : iter(3)) {
        System.out.println(i);  // 0, 1, 2
    }

    for (int i : iter(-5)) {
        System.out.println(i);  // 0, -1, -2, -3, -4
    }

    for (int i : iter(1, 7)) {
        System.out.println(i);  // 1, 2, 3, 4, 5, 6
    }

如果您要静态导入方法:

import static your.package.IterUtil.iter;

来自这个自定义类:

public class IterUtil {

    public static Iterable<Integer> iter(int to) {
        return new IntIterable(0, to);
    }

    public static Iterable<Integer> iter(int from, int to) {
        return new IntIterable(from, to);
    }


    private static class IntIterable implements Iterable<Integer> {

        private int start;
        private int end;

        private IntIterable(int start, int end) {
            this.start = start;
            this.end = end;
        }

        @Override
        public Iterator<Integer> iterator() {
            return new Iterator<Integer>() {
                private int actual = start;

                @Override
                public boolean hasNext() {
                    return actual != end;
                }

                @Override
                public Integer next() {
                    int value = actual;

                    if (actual < end) {
                        actual++;
                    } else if (actual > end) {
                        actual--;
                    }

                    return value;
                }

                @Override
                public void remove() {
                    // do nothing
                }
            };
        }
    }
}

【讨论】:

  • 一点也不傻。现在在我的测试中使用它,看看它们的可读性如何! 10 倍。
  • 哦,它是for (int i : range(1,3)) 产生1,2,3(含)
【解决方案2】:

因为数字不是范围。将数字转换为范围是不明确的。 没有什么能阻止你编写一个 可迭代的 Range 类,例如

public class IntegerRange implements Iterable<Integer> {
  private final int _fromInclusive;
  private final int _toExclusive;

  public IntegerRange(int fromInclusive, int toExclusive) {
    _fromInclusive = fromInclusive;
    _toExclusive = toExclusive;
  }

  public Iterator<Integer> iterator() {
    return new Iterator<Integer>() {
      int c = _fromInclusive;
      public boolean hasNext() {
        return c < _toExclusive;
      }

      public Integer next() {
        if (c >= _toExclusive) {
          throw new NoSuchElementException();
        }
        return c++;
      }

      public void remove() {
        throw new UnsupportedOperationException();
      }
    };
  }
}

请注意,使用这种方法,您可以轻松添加诸如指定增量、范围是否包含两边等功能。

【讨论】:

  • +1 表示 my 问题的正确答案:歧义。使用 Matej 的解决方案。代码的 10 倍。
【解决方案3】:

您迭代对象的集合。而 Integer 是一个单一的对象,没有什么可以迭代的。但是,您可以这样做:

for(int i=0;i<number;i++)

【讨论】:

  • 正是我的想法。 for(int i : 3) 循环的唯一用途是为程序员节省 10 个字符并在 for() 后端进行更多工作。
【解决方案4】:

在 java 中,foreach 循环仅遍历 数组 或实现 Iterable 接口的集合,而包装器类型 Integer 没有。

但是当你考虑它时,它是有道理的。 “对于 3 中的每个整数 i,执行此操作”是什么意思? 3 中有多少个整数?我们是否从零开始,所以有 4 个整数 (0,1,2,3)?我们从 1 开始吗?我们一定要一步一步来吗?

如果您想模拟这种行为,TheOtherGuy 的答案会起作用,但直接的 for 循环可能会更好。

【讨论】:

    【解决方案5】:

    for(x : c) 语法中,c 必须是Iterable3 不是。 你可以做

        for (int i : new int[]{0,1,2}) {
              System.out.println(i);
         }
    

    【讨论】:

    • 没有回答我的问题,而且你的 for 循环并不比旧的 C 风格好。
    【解决方案6】:

    正如其他人所指出的,Java 的 for-each 迭代一个数组或集合。 “3”不是一个数组或集合,它是一个单一的值。如果 Java 允许您建议的构造,则唯一一致的实现是“迭代”单个值 3。即:

    for (int i : 3) {   System.out.println(i); } 
    

    会输出:

    3
    

    这似乎不是很有用,这可能是他们没有实施它的原因。

    您的问题假设像“3”这样的单个值意味着一个范围。但是你为什么要假设 {0,1,2,3} ?为什么不{1,2,3}?还是 {-3, -2, -1, 0, 1, 2, 3}?还是 {0.5, 1.0, 1.5, 2.0, 2.5, 3}?或者实际上是无限数量的其他可能的变化。

    为了具体化,您必须指定起始值、结束值和增量。嗯,也许我们可以想出这样的符号:

    for (int i=0,3,1)
    

    但这仍然模棱两可。不清楚我们是要继续直到 i==3,还是直到最后一个值

    for (int i=0; i<=3; i=i+1)
    

    哦,等等,这已经被支持了。 :-)

    【讨论】:

      【解决方案7】:

      Number 具有非 Integer 子类,例如 Float 和 BigDecimal,因此在 Number 上实现 Iterable&lt;Integer&gt; 没有意义。不过,让 Integer 和 Long 实现 Iterable&lt;Integer|Long> 会很好。

      【讨论】:

      • +1 并没有以这种方式考虑数字。当然我只想要整数(从数学上讲)
      猜你喜欢
      • 2011-02-05
      • 2023-03-10
      • 1970-01-01
      • 2017-02-09
      • 1970-01-01
      • 1970-01-01
      • 2020-10-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多