2014-01-18 7 views
1

Скажем, у меня есть эта функция в Java, когда лучше сохранить результат функции, а не вызвать ее снова?

public static Character firstNonrepeatedChar(String in) { 
      int[] repeated = new int[256]; 

      for(int i=0; i<256; i++){ 
       repeated[i] = 0; 
      } 

      // First time calling in.length() 
      for(int j=0; j<in.length(); j++){ 
       repeated[in.charAt(j)]++; 
      } 

      // Second time calling in.length() 
      // I could have used "int length = in.length() and use this variable in this second loop" 
      for(int j=0; j<in.length(); j++){ 
       if(repeated[in.charAt(j)] == 1) 
        return in.charAt(j); 
      } 
      return null; 
     } 

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

+1

Метод 'length()' просто возвращает значение поля. Так что это O (1). Единственный прецедент, который я вижу, касается удобства. Если вы хотите запустить цикл для половины своей строки, вам просто нужно будет изменить значение переменной, используемой для хранения длины, вместо того, чтобы делать эти изменения во всем цикле for, который вы написали. – user2336315

+1

Я считаю, что в вашем случае затраты времени будут практически одинаковыми. В таком случае я бы выбрал удобочитаемость, т. Е. Дважды использовал вызов метода. Я думаю, что сохранение ценности имеет смысл, когда вызов метода имеет тенденцию быть медленным, и мы гарантируем, что сохраненная ценность не может измениться между ними, и есть причина сомневаться в том, что оптимизатор Java не будет обрабатывать ее самостоятельно. –

+0

['ConcurrentLinkedQueue.size()'] (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html#size%28%29) - один из примеров, когда вы должен подумать дважды, прежде чем называть это в цикле, так как это O (N) – zapl

ответ

2

в целом, оптимизируйте, когда вы можете измерить, что оптимизация 1) полезна и 2) того стоит. Стоит это, я имею в виду, что снижение удобочитаемости гарантирует увеличение производительности. Пункт 1 означает, что ваши изменения могут быть вредными или просто ничего не делать.

Например, добавление локальной переменной приведет к увеличению стека вашего метода, что может быть хуже, чем время выполнения в экстремальных средах. Кроме того, String.length() просто возвращает значение переменной, поэтому не вызывать метод не спасает вас. Ваш JIT может (и, вероятно, будет) оптимизировать условие цикла в любом случае, что означает, что ваша оптимизация не была действительно выгодной.

+1

И общее правило с современными языками заключается в том, чтобы избежать преждевременной оптимизации. –

+0

Обратите внимание, что «измерение оптимизации» должно быть в контексте фактического кода, а не для микро-теста. Если оптимизируемый код слишком мал, часть приложения для внесения изменений в измеримую разницу не оптимизирует его. –

+0

@ PM 77-1 Почему люди настаивают на том, чтобы называть такие вещи, как эта преждевременная оптимизация? Если вы напишете функцию и можете сделать что-то двумя эквивалентными способами, почему бы не выбрать способ, который может сэкономить даже крошечный раскол наносекунды? (Конечно, оба варианта верны) –

3

JIT будет встроенными простыми методами, такими как length() Если вы хотите улучшить производительность, вам придется искать разные алгоритмы.

Что-то, что вы можете сделать, это предположить, что массив уже заполнен 0, так что вам не нужно его обнулять. Примечание: у вас могут быть символы> 255.

Также я бы вернул char, так как вы не можете получить значение null.

+0

Эта вставка позволяет избежать повторного выполнения? Как он может предсказать, что значение не изменилось и кто проверяет соответствие? – Leeor

+0

@Leeor В этом случае 'length()' возвращает поле 'final'. –

+0

Кроме того, 'String' является окончательным, поэтому метод нельзя переопределить –

1

Это действительно зависит от функции, которую вы вызываете. Поскольку вы вызываете String.length(), вполне нормально вызывать его более одного раза в том же контексте, даже если возвращаемое значение не ожидается.

Однако считается, что наилучшей практикой является кэширование возвращаемых значений функции в переменных, особенно для сложных функций. В вашем случае нет большой разницы.

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