Допустим, я хочу разработать функцию, которая возвращает информацию о данной акции. Функция получает название акции в качестве параметра типа String, а затем возвращает несколько значений. Он может вернуть следующие значения:
int price
int profitability
double currentTrend
int mostRecentSpike
long timeOfRecentSpike
Как видите, все они относятся к разным примитивным типам. Мне интересно, как лучше всего вернуть эти значения с точки зрения оптимизации. Итак, если бы я создал такой пользовательский объект:
class Stock {
int price;
int profitability;
double currentTrend;
int mostRecentSpike;
long timeOfRecentSpike;
public Stock(int price, int profitability, double currentTrend, int mostRecentSpike, long timeOfRecentSpike) {
this.price = price;
this.profitability = profitability;
this.currentTrend = currentTrend;
this.mostRecentSpike = mostRecentSpike;
this.timeOfRecentSpike = timeOfRecentSpike;
}
}
и вернул это, было бы лучше, чем альтернатива, в которой я просто вернул это:
new Object[] {price, profitability, currentTrend, mostRecentSpike, timeOfRecentSpike}
а затем преобразовал все в соответствующие примитивные типы? Хотя я понимаю, что читаемость будет снижена при возврате и преобразовании Object [], меня больше всего беспокоит производительность с точки зрения ЦП, памяти и сериализации.
Эта проблема - просто метафора гораздо более серьезной проблемы, с которой я столкнулся, но в гораздо большем масштабе, требующей гораздо большего объяснения. Так что даже если в этом небольшом примере разница незначительна, в моей реальной ситуации она будет гораздо более значимой.
ЦП и память должны быть примерно одинаковыми (массивы в Java являются объектами, поэтому они такие же, как и ваш объект). Пользовательский класс лучше всего подходит для сериализации, поскольку вы можете присвоить ему фиксированный идентификатор сериализации и переопределить методы для обеспечения пользовательской сериализации, если это необходимо. Пользовательский класс также лучше подходит для чтения кода.
Верните Stock, чтобы поля сохранили свой тип и семантическое значение.
Fwiw, Google широко использует AutoValue именно для этой цели.
«Так что, даже если разница незначительна в этом небольшом примере, в моей реальной ситуации она будет гораздо более значительной». Самая большая проблема с возвратом всего содержимого Object[] состоит в том, что вы теряете семантическую информацию. Вторая по величине проблема заключается в том, что вам нужно упаковать все примитивы, что приводит к накладным расходам для каждого элемента массива. Использование настраиваемого класса позволяет вам хранить вещи как примитивы, поэтому накладные расходы вы берете только один раз на каждое возвращаемое значение.
@AndyTurner не лучше ли хранить их в коробочном формате? Итак, каждый int теперь является целым числом, long теперь Long и т. д.?
@KaelEppcohen, если вас беспокоит использование памяти, нет. int занимает 4 байта; Integer 12. Таким образом, вы можете сохранить свои 3 поля int в пространстве, которое потребуется для хранения 1 как целого числа.
@Andy Integer - как минимум 16 ...
@ Александр, моя ошибка, я думал только о накладных расходах.




Что ж, с точки зрения оптимизации, лучшая практика - вернуть объект Stock, потому что приведение приведет к гораздо большему использованию процессора и памяти и даже может привести к исключениям, таким как classCastException, если в любом случае вы пропустите какие-либо переменные.
Так,
return new Stock(price, profitability, currentTrend, mostRecentSpike, timeOfRecentSpike);
Время, которое вы потратите на отладку неправильных типов и ошибок границ массива, значительно сократит дополнительные затраты времени и памяти.
Пока ты говоришь
it will scale up to be much more significant in my actual situation.
Я подозреваю, что у вас на самом деле нет цифр, чтобы доказать это (как если бы у вас было, я сомневаюсь, вы бы здесь спросили ...)
Я бы посоветовал вам написать это как можно яснее, что, вероятно, включает передачу ссылки на реальный объект вокруг, пока вы не получите данные для доказывать, что это настоящая проблема. (В 99% случаев «очевидный» расход времени - нет)
Я собираюсь подытожить комментарии в один последовательный ответ, поскольку они во многом ответили на мой вопрос.
markspace:
Поскольку в Java массивы являются объектами, они будут иметь структуру, аналогичную пользовательскому классу Stock, и в результате потребуют по существу того же объема памяти и ресурсов ЦП.
Пользовательский класс имеет преимущество с точки зрения сериализации, поскольку он имеет фиксированный идентификатор сериализации, который также можно настроить при желании.
Пользовательский класс также улучшает читаемость.
Энди Тернер:
С помощью Object [] каждое введенное значение станет объектом, и когда вы извлечете элементы из этого массива, вам нужно будет упаковать их из объекта в их непримитивный аналог (Long, Double, Integer), который имеет некоторые накладные расходы. С настраиваемым классом вы будете хранить все как примитив, поэтому нет необходимости в боксе и, как следствие, нет накладных расходов.
Также, если вы думали об использовании непримитивных значений внутри своего пользовательского класса, это хуже с точки зрения памяти. Наличие поля типа int примерно в 4 раза эффективнее памяти, чем хранение его как Integer.