J'étais curieux de savoir quelles étaient les différences de performances entre la classe Java et le type primitif pour double. J'ai donc créé un petit benchmark et trouvé que le type de classe était 3x-7x plus lent que le type primitif. (3x sur la machine locale OSX, 7x sur ideone)
Voici le test:
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));
}
}
Alors pourquoi le type Double est-il tellement plus lent? Pourquoi est-il même implémenté pour permettre aux opérateurs mathématiques?
Alors pourquoi le type Double est-il tellement plus lent?
Parce que la valeur est enveloppée dans un objet qui nécessite une allocation, une désallocation, une gestion de la mémoire ainsi que des getters et setters
Pourquoi est-il même implémenté pour permettre aux opérateurs mathématiques?
Parce que la boîte automatique est destinée à vous permettre d'utiliser de tels wrappers sans vous soucier du fait qu'il ne s'agit pas de valeurs simples. Préféreriez-vous ne pas avoir de ArrayList<Double>
? Les performances sont pas toujours nécessaires et une baisse de 3x-7x des performances selon les situations peut être acceptable. L'optimisation est une exigence qui n'est pas toujours présente.
Cela est vrai dans toutes les situations, l'utilisation d'un LinkedList
pour des éléments d'accès aléatoire pourrait être exagéré mais cela ne signifie pas que LinkedList
ne devrait pas du tout être implémenté. Cela ne signifie pas non plus que l'utilisation d'une liste chaînée pour quelques accès aléatoires pourrait nuire autant aux performances.
ne note finale: vous devriez laisser le VM s'échauffer avant de comparer de telles choses.
Vous n'utiliseriez normalement pas Double
, Integer
, etc. (Parfois, Integer
etc. peut être utile pour stocker une valeur "facultative" - vous voudrez peut-être qu'elle soit null
parfois. C'est moins probable avec Double
car NaN
est disponible pour ceux-ci.)
La raison pour laquelle Double
existe est la suivante. Java a deux principaux types de valeur: les objets (essentiellement comme les pointeurs C/C++ sans l'arithmétique) et les valeurs primitives (par exemple double
). Les classes comme ArrayList
peut être défini pour accepter n'importe quel Object
, ce qui permet aux utilisateurs de stocker String
, File
ou tout ce qu'ils veulent en un - mais les valeurs primitives comme double
sont non couvert par une telle définition. Ainsi, des classes comme Double
existent pour faciliter le stockage de ArrayList
s par des classes comme double
, sans exiger les auteurs de ArrayList
pour créer des versions spéciales pour tous les types primitifs.
Double
est un double
encadré. Ainsi, en général, le code compilé doit vérifier le Double
pour null avant de faire quoi que ce soit avec lui. C'est bien sûr plus lent que de ne rien faire.
Double
(et d'autres versions encadrées des primitives) est utile car c'est un Object
. Cela vous permet de le transmettre aux fonctions qui prendraient un Object
, et de le restituer à Double
ailleurs. Plus utilement, il permet aux types génériques de le contenir: Un type générique ne peut pas contenir double
ou toute autre primitive, mais il peut contenir un Double
.