Ярлык Java: создание массива для изменения цикла for в цикл for-each - PullRequest
3 голосов
/ 23 июня 2011

Я рассмотрел использование этого ярлыка в моих соревнованиях по программированию.Я определяю функцию:

private static int[] range(int n) {
    int[] ret = new int[n];
    for (int i = 0; i < n; i++) {
        ret[i] = i;
    }
    return ret;
}

, чтобы я мог писать свои циклы for немного быстрее и более аккуратно (при сканировании кода):

for (int i: range(n)) { doit(i); }

вместо:

for (int i = 0; i < n; i++) { doit(i); }

Существуют ли какие-либо существенные проблемы с производительностью при таком подходе и каковы они?

Код имеет ограничение по времени для расчета решения, но, используя правильный алгоритм, он обычноВозможно сделать это за часть срока.Функция диапазона работает в O (n), и поскольку мы все равно собираемся запустить цикл O (n), временная сложность не увеличивается.Как насчет сбора мусора?Что-нибудь еще, о чем я не думаю?

Я определю, действительно ли мне нравится , используя этот метод позже, и стоит ли мне затрачивать время на ввод функций в начале соревнования, Пожалуйста, не отвечайте о стиле. (Конкурсное кодирование создает один из худших на вид кодов, который вы когда-либо видели, но все дело в том, чтобы сделать это вовремя и никогда не смотреть на него снова.)


Чтобы уточнить, фактическое время кодирования имеет решающее значение в этом конкурсе, и мы не можем принести предварительно напечатанный код.Как правило, это также означает отсутствие фрагментов кода.foreach сделает циклы for быстрее набираемыми и менее подверженными ошибкам в спешной и грязной среде программирования.Это альтернатива макросам в C ++.

Ответы [ 4 ]

2 голосов
/ 23 июня 2011

Я бы предложил использовать:

for (int i = 0; i < n; i++) { doit(i); }

, если вы ищете быстрое время выполнения.

Другой подход потребует времени при поиске в массиве и копировании значений при присвоении значения i.

Я попытался выполнить быстрый тест для проверки:

class Main {
private static int[] range(int n) {
  int[] ret = new int[n];
  for (int i = 0; i < n; i++) {
    ret[i] = i;
  }
  return ret;
}

public static void main (String[] args) throws java.lang.Exception
{
  int n = 10;
  for(int x =0; x<3; x++){

  int[] ret = range(n);
  long t1 = System.nanoTime() ;
  for (int i: ret ) { }
  long t2 = System.nanoTime() ;
  for (int i = 0; i < n; i++) { }
  long t3 = System.nanoTime() ;
  System.out.println(n + " : " + (t2-t1));
  System.out.println(n + " : " + (t3-t2));
  n = n*n;
  }  
  }
  }

Полученный результат:

10 : 1382
10 : 728
100 : 5239
100 : 1774
10000 : 450105
10000 : 1741059
2 голосов
/ 23 июня 2011

Я бы предпочел сделать это таким образом, в такой ситуации.

for (int i = 0; i < n; i++) { doit(i); }

Преобразование его в массив на самом деле не дает никакой пользы, ИМО. Производительность не сильно беспокоит меня, может быть, это будет вторым. Во-первых, я этого не делаю, потому что речь идет о написании еще одного метода, который ничего не дает. Кроме того, зачем выполнять 2 цикла, когда достаточно было бы только 1.

Если вы напишете много-много for-loops, то цикл foreach может не подойти для каждой ситуации, и в любом случае вам может понадобиться традиционный for-loop, возможно, в большинстве случаев. Вы должны учитывать проблемы, с которыми мы обычно сталкиваемся на соревнованиях по программированию. Вам может понадобиться index в цикле, чтобы сделать некоторые вычисления. Кто знает. Кроме того, я не нашел себя слишком медленным, чтобы придумать for-loop до того, как foreach вошел в Java.

Более того, на соревнованиях мы обычно не заботимся о производительности, если это не указано явно. И если это так, ваш обходной путь не будет воспринят очень положительно.

1 голос
/ 23 июня 2011

Для небольшого массива это не будет проблемой (вы можете просто протестировать его, если не уверены).

Где лучший способ сделать то же самое. Цикл Foreach может перебирать итерируемые экземпляры. Вы можете создать класс RangeIterable, реализующий Iterable, и создать статический метод RangeIterable range (int from, int to), как и вы. Это будет немного больше ООП-пути, и это будет дешевле с точки зрения памяти. И даже целочисленный бокс не будет проблемой для диапазонов внутри [-127,128], который является диапазоном по умолчанию для экземпляров типа Integer *

0 голосов
/ 23 июня 2011

Не думаю, что создание массива улучшит производительность.

Вы также можете посмотреть на это:

Преждевременная оптимизация - корень всех зол1006 *

...