【问题标题】:Is there any way to shorten a for-each loop in java?有没有办法缩短java中的for-each循环?
【发布时间】:2017-02-18 04:52:37
【问题描述】:

我想只迭代 java 中数组的一半。有没有什么优雅的方法可以缩短这个时间,例如使用 for-each 循环?

int[] array = {0,1,2,3,4,5};

for (int i = 0; i<array.length/2; i++)
{
    System.out.println(array[i]);
}

【问题讨论】:

  • 你的代码有问题吗?
  • 不,这是完美的,随它去,但删除0+
  • 您可以删除 0+ 部分 - 它不会添加任何有用的内容。
  • 除了您添加到 array.length 的不需要的 0 之外,此代码非常完美。
  • 代码很好,表达了意图。但如果你愿意,你可以得到一个(一半)range of the array,然后做一个for(Integer i:array)

标签: java arrays foreach iteration


【解决方案1】:

怎么样:

IntStream.range(0, array.length / 2).map(i -> array[i]).forEach(System.out::println);

一行,没有数组副本。

分解:

IntStream.range(0, array.length / 2)    //get the range of numbers 0 - (array length)/2
         .map(i -> array[i])            //map from index to value
         .forEach(System.out::println); //print result

【讨论】:

    【解决方案2】:

    您发布的答案很好。虽然,我找不到更好的方法来使其紧凑并保持性能不变,但性能可以提高。在编码时记住以下做法:

    1. 算法的内存需求应该是最优的
    2. 算法的时间,即性能应该是最佳的
    3. 算法的复杂度不应该太多。对于 1 和 2 中的显着收益,可以跳过此步骤。
    4. 考虑到 1 和 2,代码行至少具有优先级。

    解决方案 1:此解决方案将比您的方法慢 4-5 倍,而且Stream 会占用额外空间。

    Arrays.stream(array).limit(array.length/2).forEach(System.ou‌​t::println);
    

    解决方案 2: 此解决方案比上述代码和您的代码(基于我的测试)要快,但 Stream 会占用额外空间。此外,它并不紧凑。

    Arrays.stream(array).limit(array.length / 2).forEach(new IntConsumer() {
        @Override
        public void accept(int value) {
            System.out.println(value);
        }
    });
    

    解决方案 3:按照您的建议。

    int[] array = new int[] { 0, 1, 2, 3, 4, 5 };
    int limit = array.length / 2;
    for (int i = 0; i < limit; i++) {
        System.out.println(array[i]);
    }
    

    建议:不要为了降低LOC而牺牲性能和内存。最好跟上为您提供最佳性能的解决方案..

    【讨论】:

    • 你对你的“慢 100-200 倍”资格有任何证明吗? “巨大的内存需求”也一样?
    • 您的解决方案 2 只不过是扩展形式的解决方案 1。在这里,您对性能提出了更加古怪的说法。您真的不应该在没有尝试验证的情况下提出绝对毫无根据的主张。
    • 我只是使用 JMH 来衡量性能,它在所有情况下都相同
    • @MarkoTopolnik 嗨..我已经在我的机器上测试过了。对于简单数组,大约需要 0.3 毫秒,而对于解决方案 1,需要 80-90 毫秒。关于方案二和方案一的区别,请参考this post。我的系统配置也在那里。
    • 第一步:了解在 JVM 上运行微基准测试意味着什么。 stackoverflow.com/questions/504103/… 第二步:学习如何使用JMH。 openjdk.java.net/projects/code-tools/jmh
    【解决方案3】:

    如果你使用Java中Arrays类的asList方法将数组转换为列表,那么你可以使用Java中List类中的forEach方法打印出每个元素单行列出,

    Arrays.asList(array).forEach(System.out::println);
    

    要只打印一半数组,我建议使用copyOfRange 方法将一半数组复制到一个新数组中,

    Integer[] newArray = Arrays.copyOfRange(array, 0, array.length/2);
    Arrays.asList(newArray).forEach(System.out::println);
    

    编辑: 就像 Marko Topolnik 指出的那样,我们实际上是从原始类型数组而不是对象类型开始的,所以为了使用 asList 方法,我们将不得不将数组转换为对象数组(从intInteger,使用Integer[] integerArray = ArrayUtils.toObject(array);)。但是,这似乎很乏味/效率低下,并且 OP 要求使用更短的方法,所以我的建议是使用 Marko 的方法,

    Arrays.stream(array).limit(array.length/2).forEach(System.ou‌​t::println);
    

    编辑 2: 就像 Amber Beriwal 指出的那样,应该注意的是,虽然上面的单行解决方案由于其简洁性而看起来很漂亮,但与 OP 的原始解决方案相比,它仍然非常低效/缓慢方法。因此,我想重申 Amber 的 cmets,即 OP 和其他人应该坚持原来的 for 循环。

    for (int i = 0; i < array.length/2; i++)
    {
        System.out.println(array[i]);
    }
    

    【讨论】:

    • @MarkoTopolnik 我的错误让我修改我的答案
    • 实际上它会打印出类似[I@343af45;的东西,因为它是一个原始数组,会变成一个单一成员List&lt;int[]&gt;
    • 使用Arrays.stream(array).limit(array.length/2).forEach(System.out::println);
    • 会比niks共享的代码慢15-20倍左右。
    • @AmberBeriwal 尽管此解决方案效率低下,但 OP 的主要关注点是编写 for 循环的方式更短,而不是更快。
    猜你喜欢
    • 1970-01-01
    • 2010-10-03
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多