Что не так с моей логикой здесь? - PullRequest
1 голос
/ 13 апреля 2010

В java говорят, что не объединять строки, вместо этого вы должны создать строковый буфер и продолжать добавлять к нему, а затем, когда все закончите, используйте toString (), чтобы получить объект String из него. Вот что я не понимаю. Говорят, делают это по соображениям производительности, потому что конкатенация строк создает много временных объектов. Но если бы целью была производительность, то вы бы использовали такой язык, как C / C ++ или ассемблер.

Аргумент за использование java заключается в том, что купить более быстрый процессор намного дешевле, чем платить старшему программисту за быстрый и эффективный код. Итак, с одной стороны, вы должны позволить аппаратному обеспечению позаботиться о неэффективности, но с другой стороны, вы должны использовать строковые буферы, чтобы сделать Java более эффективным.

Хотя я вижу, что вы можете использовать и Java, и stringbuffers, мой вопрос в том, в чем заключается ошибка в логике, что вы используете более быстрый чип или потратили дополнительное время на написание более эффективного программного обеспечения.

Ответы [ 7 ]

5 голосов
/ 13 апреля 2010

Разработчики должны понимать производительность последствия из их варианты кодирования.

Не очень сложно написать алгоритм, который приводит к нелинейной производительности - полиномиальный, экспоненциальный или хуже. Если вы в какой-то степени не понимаете, как язык, компилятор и библиотеки поддерживают ваш алгоритм, вы можете оказаться в ловушке, из-за которой никакая вычислительная мощность не вырвет вас. Алгоритмы, чье время выполнения или использование памяти экспоненциально, могут быстро превысить способность любого оборудования выполнять в разумные сроки.

Предполагать, что аппаратное обеспечение может масштабироваться до плохо спроектированного выбора алгоритма / кодирования, - плохая идея. Возьмем, например, цикл, который объединяет 100 000 небольших строк (например, в сообщение XML). Это не редкая ситуация - но при реализации с использованием конкатенации отдельных строк (а не StringBuffer) это приведет к 99 999 промежуточным строкам увеличивающегося размера, которые должен утилизировать сборщик мусора. Это может легко привести к сбою операции, если не хватает памяти - или, в лучшем случае, для запуска потребуется вечность.

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

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

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

4 голосов
/ 13 апреля 2010

Аргумент о том, что вы должны использовать StringBuffer, а не конкатенацию, является старым мифом о культовом грузе Java. Сам компилятор Java преобразует серию конкатенаций в один вызов StringBuffer, что делает эту «оптимизацию» совершенно ненужной в исходном коде.

Сказав это, есть законные причины для оптимизации, даже если вы используете «медленный» байт-код или интерпретируемый язык. Вы не хотите иметь дело с ошибками, нестабильностью и более длительным циклом разработки C / C ++, поэтому вы используете язык с более широкими возможностями. (Встроенные строки, где!) Но в то же время вы хотите, чтобы ваш код работал с этим языком как можно быстрее, поэтому вы избегаете явно неэффективных конструкций. IOWs только потому, что вы отказываетесь от некоторой скорости с помощью Java, не означает, что вы должны полностью забыть о производительности.

3 голосов
/ 13 апреля 2010

Разница в том, что StringBuffer совсем не сложнее и не требует больше времени, чем конкатенация строк. Общий принцип заключается в том, что если возможно повысить эффективность без увеличения времени / сложности разработки, это следует сделать: ваш принцип применяется только тогда, когда это невозможно.

2 голосов
/ 13 апреля 2010

Более медленный язык не является оправданием для использования гораздо более медленного алгоритма (а в наши дни Java не так уж и медленен).

Если мы объединяем 1-символьную строку в n-символьную, нам нужно скопировать n + 1 символов в новую строку. Если мы сделаем

string s;
for (int i = 0; i < N; ++ i)
  s = s + "c";

тогда время работы будет O (N 2 ).

В отличие от этого, строковый буфер поддерживает изменяемый буфер, который сокращает время работы до O (N).

Вы не можете удвоить ЦП, чтобы превратить квадратичный алгоритм в линейный.

(Хотя оптимизатор уже неявно создал для вас StringBuffer.)

1 голос
/ 13 апреля 2010

В реальном мире языки программирования, операционные системы и инструменты разработки не выбираются людьми, которые фактически будут иметь дело с этим.

Некоторые продавцы компании А пообедают с вашим боссом, чтобы продать его операционную систему ... а затем другой продавец пригласит вашего босса на стриптизерши, чтобы продать его механизм базы данных ... и так далее.

Тогда, и только тогда, они нанимают кучку программистов, чтобы собрать все это вместе. Они хотят, чтобы это было красиво, быстро и дешево.

Именно поэтому вы можете в конечном итоге программировать высокопроизводительные приложения на Java на мобильном устройстве или на 3D-графике для Windows на Python ...

Итак, ваше право, но это не имеет значения. :)

1 голос
/ 13 апреля 2010

Java! = Неэффективный код.

Вы не покупаете более быстрый процессор, чтобы избежать написания эффективного кода. Плохой программист напишет плохой код независимо от языка. Аргумент, что C / C ++ более эффективен, чем Java, - старый аргумент, который больше не имеет значения.

0 голосов
/ 13 апреля 2010

Вы всегда должны размещать оптимизации там, где можете. Вы не должны «лениво кодировать» только потому, что у вас быстрый процессор ...

Я действительно не знаю, как работает stringbuffer, и при этом я не работаю с Java, но предполагая, что java определяет строку как char [], вы выделяете тонну фиктивных строк при выполнении str1 + str2 + str3 + str4 + str5, где вам действительно нужно только сделать строку длиной str1.length + ... str5.length и скопировать все ОДИН РАЗ ...

Однако, умный компилятор оптимизирует и автоматически использует stringbuffer

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...