Java Double vs double: тип класса vs примитивный тип
Мне было любопытно, каковы различия в производительности между классом Java и примитивным типом для double. Поэтому я создал небольшой тест и нашел тип класса на 3x-7x медленнее, чем примитивный тип. (3x на локальной машине OSX, 7x на ideone)
Вот тест:
class Main {
public static void main(String args[]) {
long bigDTime, littleDTime;
{
long start = System.nanoTime();
Double d = 0.0;
for (Double i = 0.0; i < 1432143.341; i += 0.1) {
d += i;
}
long end = System.nanoTime();
bigDTime = end - start;
System.out.println(bigDTime);
}
{
long start = System.nanoTime();
double d = 0.0;
for (double i = 0.0; i < 1432143.341; i += 0.1) {
d += i;
}
long end = System.nanoTime();
littleDTime = end - start;
System.out.println(littleDTime);
}
System.out.println("D/d = " + (bigDTime / littleDTime));
}
}
http://ideone.com/fDizDu
Так почему же тип Double намного медленнее? Почему это даже реализовано для использования математических операторов?
Ответы
Ответ 1
Так почему же тип Double намного медленнее?
Так как значение обернуто внутри объекта, который требует выделения, освобождения памяти, управления памятью и геттеров и сеттеров
Почему это даже реализовано для обеспечения математических операторов?
Поскольку autobox предназначен для того, чтобы вы могли использовать такие обертки, не беспокоясь о том, что они не являются простыми значениями. Вы предпочли бы не иметь ArrayList<Double>
? Производительность не всегда необходима, и падение производительности 3x-7x в зависимости от ситуации может быть приемлемым. Оптимизация - это требование, которое не всегда присутствует.
Это верно в любой ситуации, использование элементов LinkedList
для случайного доступа может быть чрезмерным, но это не означает, что LinkedList
не должно быть реализовано вообще. Это не означает, что использование связанного списка для нескольких случайных доступов может сильно повлиять на производительность.
Окончательная заметка: вы должны позволить VM разогреться перед сравнением таких вещей.
Ответ 2
Обычно вы не использовали Double
, Integer
и т.д. (Иногда Integer
и т.д. может быть полезно для хранения "необязательного" значения - иногда это может быть null
. менее вероятно с Double
, потому что NaN
доступен для них.)
Причина Double
существует следующим образом. Java имеет два основных типа значения: объекты (по существу, как указатели C/С++ без арифметики) и примитивные значения (например, Double
). Классы типа ArrayList
могут быть определены для принятия любого Object
, который позволяет пользователям хранить String
, File
или все, что им нравится в одном, но примитивные значения, такие как Double
, не охватываются таким определением. Таким образом, существуют классы типа Double
, чтобы упростить для таких классов, как ArrayList
, сохранение Double
s, не требуя от авторов ArrayList
создания специальных версий для всех примитивных типов.
Ответ 3
Double
представляет собой коробку Double
. Таким образом, в общем случае скомпилированный код должен проверять Double
на null, прежде чем что-либо делать с ним. Это, конечно, медленнее, чем ничего не делать.
Double
(и другие вложенные версии примитивов) полезно, потому что это Object
. Это позволяет вам передать его функции, которые будут принимать Object
, и отбросить ее обратно в Double
в другом месте. Более полезно, он позволяет содержать общие типы: общий тип не может содержать Double
или любой другой примитив, но может содержать Double
.