java-8 d'objet - En Java 8, pourquoi la capacité par défaut de ArrayList est-elle maintenant nulle?




afficher une (6)

La question est "pourquoi?".

Les inspections de profilage de la mémoire (par exemple ( https://www.yourkit.com/docs/java/help/inspections_mem.jsp#sparse_arrays ) montrent que les tableaux vides (remplis avec des valeurs nulles) occupent des tonnes de mémoire.

La taille par défaut de 10 objets signifie que nous allouons 10 pointeurs (40 ou 80 octets) pour le tableau sous-jacent à la création et les remplissons avec des valeurs nulles. Les applications Java réelles créent des millions de listes de tableaux.

La modification introduite supprime ^ W reporter cette consommation de mémoire jusqu'au moment où vous utiliserez réellement la liste de tableau.

Si je me souviens bien, avant Java 8, la capacité par défaut de ArrayList était de 10.

Étonnamment, le commentaire sur le constructeur par défaut (void) dit toujours: Constructs an empty list with an initial capacity of ten.

De ArrayList.java :

/**
 * Shared empty array instance used for default sized empty instances. We
 * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
 * first element is added.
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

...

/**
 * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

La taille par défaut de ArrayList dans JAVA 8 est de 10 octets. La seule modification apportée dans JAVA 8 est que si un codeur ajoute des éléments inférieurs à 10, alors les espaces vides de l'arborescence restante ne sont pas spécifiés sur null. Dire cela parce que j'ai moi-même traversé cette situation et éclipse m'a fait regarder dans ce changement de JAVA 8.

Vous pouvez justifier ce changement en regardant la capture d'écran ci-dessous. Dans celui-ci vous pouvez voir que la taille ArrayList est spécifiée comme 10 dans l'objet [10] mais le nombre d'éléments affichés est seulement 7. Les éléments restants de la valeur nulle ne sont pas affichés ici. Dans JAVA 7, la capture d'écran ci-dessous est identique avec un seul changement: les éléments de valeur nulle sont affichés pour lesquels le codeur doit écrire du code pour gérer les valeurs nulles s'il itère la liste complète des tableaux alors que dans JAVA 8 cette charge est supprimée. la tête du codeur / développeur.

Lien de capture d'écran.


Si la toute première opération effectuée avec une ArrayList est de transmettre à addAll une collection qui a plus de dix éléments, alors tout effort mis dans la création d'un tableau initial de dix éléments pour contenir le contenu de ArrayList serait rejeté par la fenêtre. Chaque fois que quelque chose est ajouté à une ArrayList, il est nécessaire de tester si la taille de la liste résultante dépassera la taille du magasin de sauvegarde; Le fait que le magasin de sauvegarde initial ait la taille zéro plutôt que dix entraînera l'échec de ce test une fois de plus dans la durée de vie d'une liste dont la première opération est un ajout qui nécessiterait la création du tableau initial de dix éléments. moins que le coût de la création d'un tableau de dix éléments qui ne finit jamais par être utilisé.

Cela étant dit, il aurait peut-être été possible d'améliorer davantage les performances dans certains contextes s'il y avait une surcharge de "addAll" qui spécifiait combien d'éléments (le cas échéant) seraient probablement ajoutés à la liste après la présente, et qui pourraient l'utiliser pour influencer son comportement d'allocation. Dans certains cas, le code qui ajoute les derniers éléments à une liste aura une très bonne idée que la liste n'aura jamais besoin d'espace au-delà. Il existe de nombreuses situations où une liste sera remplie une fois et ne sera jamais modifiée par la suite. Si le code de point sait que la taille finale d'une liste sera de 170 éléments, il a 150 éléments et un magasin de backing de taille 160, la croissance du backing store vers la taille 320 sera inutile et la laissera à la taille 320 ou 170 sera moins efficace que de simplement faire passer la prochaine allocation à 170.


En java 8, la capacité par défaut de ArrayList est 0 jusqu'à ce que nous ajoutions au moins un objet dans l'objet ArrayList (vous pouvez l'appeler initialisation paresseuse). S'il vous plaît voir ci-dessous le code pour l'aide.

ArrayList al = new ArrayList();          //Size:  0, Capacity:  0
ArrayList al = new ArrayList(5);         //Size:  0, Capacity:  5
ArrayList al = new ArrayList(new ArrayList(5)); //Size:  0, Capacity:  0
al.add( "shailesh" );                    //Size:  1, Capacity: 10

public static void main( String[] args )
        throws Exception
    {
        ArrayList al = new ArrayList();
        getCapacity( al );
        al.add( "shailesh" );
        getCapacity( al );
    }

    static void getCapacity( ArrayList<?> l )
        throws Exception
    {
        Field dataField = ArrayList.class.getDeclaredField( "elementData" );
        dataField.setAccessible( true );
        System.out.format( "Size: %2d, Capacity: %2d%n", l.size(), ( (Object[]) dataField.get( l ) ).length );
}

Response: - 
Size:  0, Capacity:  0
Size:  1, Capacity: 10

Maintenant, la question est pourquoi ce changement a été fait dans JAVA 8?

La réponse est d'économiser la consommation de mémoire. Des millions d'objets de liste de tableaux sont créés dans des applications Java en temps réel. La taille par défaut de 10 objets signifie que nous allouons 10 pointeurs (40 ou 80 octets) pour le tableau sous-jacent à la création et les remplissons avec des valeurs nulles. Un tableau vide (rempli de zéros) occupe beaucoup de mémoire.

L'initialisation paresseuse retarde cette consommation de mémoire jusqu'au moment où vous utiliserez la liste de tableaux.

Article La capacité par défaut de ArrayList dans Java 8 l' explique en détails.


Après la question ci-dessus je suis passé par ArrayList Document de Java 8. J'ai trouvé la taille par défaut est toujours 10 seulement.


La capacité initiale ne fait qu'une chose: elle donne une suggestion (pas une exigence) de la taille du tableau de sauvegarde. Logiquement, il n'y a pas de différence entre les opérations autorisées avec ou sans la suggestion ou la suggestion. Les seules modifications concerneront les opérations internes susceptibles de se produire ou non en tant que suggestion d'optimisation.

Vous ne pouvez «ajouter» comme cela qu'aux positions qui existent déjà dans le tableau. Les éléments avant la position 5 n'existent pas encore, il jette donc une exception. Du Javadoc :

Lance: IndexOutOfBoundsException - si l'index est hors limites (index <0 || index> size ())







java arraylist java-8