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.