рефакторинг массивов Java и примитивов (дважды [] []) к Наборам и Дженерикам (Список <Список <Дважды>>)

"Со строгим контролем типов" и "со слабым контролем типов" условия, которые имеют не широко согласованный техническое значение. Условия, которые действительно имеют четко определенное значение,

  • С динамическим контролем типов средства, которые типы присоединены к значениям во время выполнения, и попытка смешать значения различных типов может вызвать "ошибку типа выполнения". Например, если в Схеме Вы попытаетесь добавить ту к истинному путем записи (+ 1 #t), то это вызовет ошибку. Вы встречаетесь с ошибкой, только при попытке выполнить незаконный код.

  • Со статическим контролем типов средства, которые типы проверяются во время компиляции, и программа, которая не имеет статического типа, отклоняется компилятором. Например, если в ML Вы попытаетесь добавить тот к истинному путем записи 1 + true, программа будет отклонена с (вероятно, загадочный) сообщение об ошибке. Вы всегда получаете ошибку, даже если код никогда не мог бы выполняться.

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

Иногда "со строгим контролем типов" используется свободно для значения "со статическим контролем типов", и "со слабым контролем типов" используется неправильно для значения "с динамическим контролем типов". Лучшее использование для термина "со строгим контролем типов" состоит в том, что "Вы не можете работать вокруг или ниспровергать систему типов", тогда как "со слабым контролем типов" означает, что "в системе типов существуют лазейки". Упрямо, большинство языков со статическими системами типов имеет лазейки, в то время как много языков с динамическими системами типов не имеют никаких лазеек.

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

, Если Вы хотите говорить точно о языках программирования, лучше избегать условий, "со строгим контролем типов" и "со слабым контролем типов". Я сказал бы, что C является языком, который со статическим контролем типов, но это имеет много лазеек. Одна лазейка - то, что можно свободно бросить любой тип указателя к любому другому типу указателя. Можно также создать лазейку между любыми двумя типами по Вашему выбору путем объявления объединения C, которое имеет двух участников, один для каждого из рассматриваемых типов.

я записал больше о статическом контроле типов и динамическом контроле типов в why-interpreted-langs-are-mostly-ducktyped-while-compiled-have-strong-typing.

5
задан Community 23 May 2017 в 12:07
поделиться

7 ответов

Я прочитал отличную книгу Кента Бека о передовых методах программирования ( http://www.amazon.com/Implementation-Patterns/dp/B000XPRRVM ). Есть и интересные показатели производительности. В частности, есть сравнение между массивами и различными коллекциями. И массивы действительно намного быстрее (возможно, в 3 раза по сравнению с ArrayList).

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

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


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

Однако, если вам не нравится, что верхняя граничная переменная, используемая только в цикле, доступна вне цикла, вы можете воспользоваться фазой инициализации for такой цикл:

    for (int i=0, max=list.size(); i<max; i++) {
      // do something
    }

Я не верю в устаревание массивов в java. Что касается цикла, критичного к производительности, я не вижу, чтобы разработчик языка отказался от самого быстрого варианта (особенно если разница в 3 раза).


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

Я бы попытался сделать код максимально ясным, не меняя его:

  • путем тщательного опроса каждого имени переменной , в идеале с 10-минутным сеансом мозгового штурма с моими коллегами
  • путем написания комментариев по кодированию (я против их использования в целом, поскольку непонятный код следует разъяснять, а не комментировать; но критический цикл оправдывает это)
  • с использованием частных методов по мере необходимости (как указал Andreas_D в своем ответе). Если сделать private final , очень высоки шансы (поскольку они будут короткими), что они будут встроены во время работы, поэтому не будет никакого влияния на производительность во время выполнения.
7
ответ дан 18 December 2019 в 10:46
поделиться

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

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

Вы также можете сталкиваются с проблемами автоматической упаковки при упаковке / распаковке двойников - потенциально более тонкая проблема.

Ребята, занимающиеся языком Java, очень строго следят за совместимостью JVM в разных версиях, поэтому я не вижу, чтобы массивы никуда не делись - и я не назвал бы их устаревшими, просто более примитивными, чем другие варианты.

3
ответ дан 18 December 2019 в 10:46
поделиться

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

double[][] matrix = new double[10][10];
double t = matrix[0][0];

List<List<Double>> matrix = new ArrayList<List<Double>>(10);
Collections.fill(matrix, new ArrayList<Double>(10));
double t = matrix.get(0).get(0); // autoboxing => performance

Насколько я знаю, Java предварительно сохраняет некоторые объекты-оболочки для экземпляров Number (например, первых 100 целых чисел), чтобы вы могли получить к ним доступ быстрее, но я думаю, что это не очень поможет с таким количеством данных.

2
ответ дан 18 December 2019 в 10:46
поделиться

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

0
ответ дан 18 December 2019 в 10:46
поделиться

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

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

Для ясности, взаимодействие с остальной частью кода Я бы хотел его реорганизовать.

Вместо изменения структуры данных я бы сосредоточился на переименовании и, возможно, перемещении некоторой части кода в частные методы. Глядя на код, я понятия не имею, что происходит, и проблема, как мне кажется, заключается в более или менее коротких технических именах переменных и полей.

Просто пример: один двумерный массив просто назван «матрица». Но очевидно, что это матрица, поэтому называть ее «матрицей» излишне. Полезнее было бы переименовать ее, чтобы стало понятно, для чего на самом деле используется эта матрица, какие данные внутри.

Другой кандидат - ваша вторая линия. С помощью двух рефакторингов я бы переименовал jj во что-нибудь более значимое и переместил выражение в частный метод с «говорящим» именем.

3
ответ дан 18 December 2019 в 10:46
поделиться

Я думаю, что вы можете не только придерживаться массивов, но и значительно улучшить этот код. Например:

  • Действительно, не вычисляйте границы цикла каждый раз, сохраните их вне
  • Вы неоднократно ссылаетесь на матрицу [i]. Просто сохраните ссылку на этот подмассив вместо того, чтобы каждый раз разыменовывать 2D-массив
  • Этот трюк становится еще более полезным, если вы можете перебирать i во внешнем цикле вместо внутреннего
  • Это становится экстремальным, но сохраняет значение of j-1 в локальном может даже оказаться оправданным, а не пересчитывать
  • Наконец, если вы действительно действительно беспокоитесь о производительности, запустите оптимизатор ProGuard над полученным байтовым кодом, чтобы он выполнил некоторые оптимизации компилятора, такие как развертка или оптимизация с помощью глазка
0
ответ дан 18 December 2019 в 10:46
поделиться

Я думал, что компиляторы должны были быть Умно, делая такую ​​вещь. Делать Нам нужно все еще сделать это?

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

1
ответ дан 18 December 2019 в 10:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: