JavaRush /Blog Java /Random-FR /new ArrayList(????) comment et où est-il préférable d'ini...
Vovan
Niveau 22

new ArrayList(????) comment et où est-il préférable d'initialiser

Publié dans le groupe Random-FR
Écrire du code sans utiliser le framework de collections serait fou. C'est un merveilleux morceau de Java avec de nombreuses solutions intéressantes. Plus important encore, contrairement aux tableaux, vous n'avez pas à vous soucier des tailles. L'ArrayList grandira jusqu'à manquer de mémoire. Le développeur n'a pas à se soucier de la taille initiale et de l'erreur ArrayIndexOutOfBoundsException . Mais que se passe-t-il s’il existe une condition pour surveiller la quantité de mémoire ? Pouvons-nous utiliser efficacement la mémoire lorsque nous travaillons avec des collections ?
Une question classique se pose : comment initialiser une liste ? Le code ci-dessous ne fonctionnera pas : Il en résultera une erreur de compilation : Les noms des variables locales n'ont peut-être pas été initialisés . La spécification Java exige que toutes les variables locales (celles qui existent sur la pile) soient initialisées avec les valeurs appropriées. Voici comment procéder : Sans aucun doute, la liste doit être initialisée. Vous pouvez soit créer la liste sur la première ligne, soit faire quelque chose de plus intelligent et utiliser une initialisation paresseuse comme nous l'avons fait dans la méthode getAllNames() . Dans ce cas, la liste ne sera créée que lorsque cela sera nécessaire - si les conditions initiales ne sont pas remplies, la liste n'apparaîtra jamais sur le tas. Nous arrivons ici à la question principale : quelle taille devons-nous définir pour la liste ? La meilleure option est de lui donner la taille exacte. Par exemple : dans ce cas, exactement n noms doivent être renvoyés et, par conséquent, une collection de n éléments est créée. Cependant, la valeur exacte de n n’est pas toujours connue. Même dans l’exemple donné, que se passerait-il si n = 1 000 et qu’il n’y avait que 100 noms disponibles ? Lorsque vous travaillez avec des collections, la méthode la plus courante consiste à appeler le constructeur par défaut. Si vous regardez le code source Java (version 1.6) Comme vous pouvez le constater, par défaut une liste de 10 éléments est créée . Autrement dit, nous pouvons utiliser en toute sécurité le constructeur par défaut lorsque nous ne prévoyons pas de stocker plus de 10 éléments dans la liste. Que se passe-t-il si vous essayez d'ajouter le 11ème élément ? Eh bien, rien de mal... l'élément sera ajouté avec succès. Regardez la méthode : La taille du tableau est contrôlée par la méthode EnsureCapacity . La taille augmente de 1,5 fois . Un nouveau tableau est créé et les éléments y sont déplacés. Si on fixe la taille à 10, alors sur le 11ème élément :
public List getAllNames() { List names; if (/*необходимые условия выполнены*/) { names = new ArrayList (); /*заполнение списка*/ } return names; }
List names = null; List names = new ArrayList (); List names = new ArrayList (0); List names = new ArrayList (size);
public List getTopNames (int n) { List names = null; if ( /*необходимые условия выполнены*/) { names = new ArrayList (n); /*заполнение списка*/ } return names; }
names = new ArrayList ();

/** * Конструирует пустой список с указанной начальной емкостью. * * @param initialCapacity начальная емкость списка * @exception IllegalArgumentException если указанная начальная емкость отрицательна * */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) this.elementData = new Object[initialCapacity]; } /** * Конструирует пустой список с начальной емкостью, равной 10. */ public ArrayList() { this(10); }
public Boolean add(E e) { ensureCapacity(size + 1); //увеличивает modCount!! elementData[size++] = e; return true; } public void ensureCapacity (int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { throw new IllegalArgumentException(“Illegal Capacity: ” + initialCapacity); Object oldData[] = elementData; int newCapacity = (oldCapacity * 3) / 2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity обычно ближе к размеру, так что это беспроигрышно: elementData = Arrays.copyOf(elementData, newCapacity); } }
  • la taille passe à 10 * 3 / 2 + 1 = 16
  • prochaine augmentation = 16 * 3 / 2 + 1 = 25
  • augmentation suivante = 25 * 3 / 2 + 1 = 39 et ainsi de suite.
Dans le cas de 100 éléments, la JVM devra créer plusieurs fois un nouveau tableau et y copier les éléments. Compte tenu de cela, s'il existe une hypothèse sur la taille requise du réseau, il est préférable de définir la capacité initiale à proximité de celle-ci. Voici quelques lignes directrices pour agir :
  1. Créez une collection uniquement lorsque vous en avez besoin , sinon initialisez-la à null ou utilisez Collections.EMPTY_LIST .
  2. Si vous connaissez la taille exacte requise , spécifiez-la dans le constructeur de collection.
  3. Si vous êtes sûr que le nombre d'éléments ne dépassera pas 10 , n'hésitez pas à utiliser le constructeur par défaut.
  4. Le risque associé à la création d'une collection de taille nulle est que la fréquence de création de nouveaux tableaux et de copie des données peut être plus élevée. Vous devez réfléchir très attentivement à la question de savoir si l'avantage de l'utilisation de collections de taille nulle est vraiment si important .
  5. Si vous avez initialisé une collection trop volumineuse au début de la méthode et que vous souhaitez la réduire, il existe la méthode trimToSize() .
Bien entendu, ces directives s'appliquent lorsque vous travaillez avec des collections basées sur des tableaux, et rien de tout cela n'a de sens dans le cas d'une liste chaînée. En fait, il est peu probable que ces problèmes tuent le programme, mais s’il existe une opportunité de faire un peu mieux, pourquoi ne pas l’utiliser. Avez-vous d'autres conseils utiles ? Avez-vous trouvé des moyens d’améliorer le fonctionnement des choses ? Ou est-ce que tout cela est inutile ? Qu'en penses-tu?
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION