Técnicamente, no es 10
cero, si admite una inicialización perezosa de la matriz de respaldo. Ver:
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
dónde
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
A lo que se refiere es solo al objeto de matriz inicial de tamaño cero que se comparte entre todos los ArrayList
objetos inicialmente vacíos . Es decir, la capacidad de 10
está garantizada de forma perezosa , una optimización que está presente también en Java 7.
Es cierto que el contrato de constructor no es del todo exacto. Quizás esta sea la fuente de confusión aquí.
Antecedentes
Aquí hay un correo electrónico de Mike Duigou
He publicado una versión actualizada del parche ArrayList y HashMap vacío.
http://cr.openjdk.java.net/~mduigou/JDK-7143928/1/webrev/
Esta implementación revisada no introduce nuevos campos en ninguna de las clases. Para ArrayList, la asignación diferida de la matriz de respaldo ocurre solo si la lista se crea con el tamaño predeterminado. Según nuestro equipo de análisis de rendimiento, aproximadamente el 85% de las instancias de ArrayList se crean con el tamaño predeterminado, por lo que esta optimización será válida para una gran mayoría de casos.
Para HashMap, se hace un uso creativo del campo de umbral para rastrear el tamaño inicial solicitado hasta que se necesita la matriz de cubos. En el lado de lectura, el caso del mapa vacío se prueba con isEmpty (). En el tamaño de escritura, se utiliza una comparación de (tabla == EMPTY_TABLE) para detectar la necesidad de inflar la matriz de cubos. En readObject hay un poco más de trabajo para intentar elegir una capacidad inicial eficiente.
De: http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-April/015585.html
getCapacity()
método, ni nada por el estilo. (Dicho esto, algo así como noensureCapacity(7)
es una operación para una ArrayList inicializada por defecto, así que supongo que realmente se supone que debemos actuar como si su capacidad inicial fuera realmente 10 ...)ArrayList
creado con el constructor no-arg en lugar de pasar cero alint
constructor, y si observa el tamaño de la matriz interna de forma reflexiva o en un depurador. En el caso predeterminado, la matriz salta de la longitud 0 a 10, luego a 15, 22, siguiendo la tasa de crecimiento de 1.5x. Pasar cero como capacidad inicial da como resultado un crecimiento de 0 a 1, 2, 3, 4, 6, 9, 13, 19 ...emptyList()
aún consume menos memoria que variasArrayList
instancias vacías . Es menos importante ahora y, por lo tanto, no es necesario en todos los lugares, especialmente en lugares con una mayor probabilidad de agregar elementos en un momento posterior. También tenga en cuenta que a veces desea una lista vacía inmutable y luegoemptyList()
es el camino a seguir.En java 8, la capacidad predeterminada de ArrayList es 0 hasta que agreguemos al menos un objeto en el objeto ArrayList (puede llamarlo inicialización diferida).
Ahora la pregunta es ¿por qué se ha realizado este cambio en JAVA 8?
La respuesta es ahorrar consumo de memoria. Se crean millones de objetos de lista de matrices en aplicaciones Java en tiempo real. El tamaño predeterminado de 10 objetos significa que asignamos 10 punteros (40 u 80 bytes) para la matriz subyacente en la creación y los completamos con nulos. Una matriz vacía (llena de nulos) ocupa mucha memoria.
La inicialización perezosa pospone este consumo de memoria hasta el momento en que realmente utilizará la lista de matrices.
Consulte el código a continuación para obtener ayuda.
Artículo La capacidad predeterminada de ArrayList en Java 8 lo explica en detalle.
fuente
Si la primera operación que se realiza con una ArrayList es pasar
addAll
una colección que tiene más de diez elementos, entonces cualquier esfuerzo realizado para crear una matriz inicial de diez elementos para contener el contenido de ArrayList se eliminaría por la ventana. Siempre que se agrega algo a una ArrayList, es necesario probar si el tamaño de la lista resultante excederá el tamaño del almacén de respaldo; Permitir que la tienda de respaldo inicial tenga un tamaño de cero en lugar de diez hará que esta prueba falle una vez más en la vida útil de una lista cuya primera operación es una "adición" que requeriría crear la matriz inicial de diez elementos, pero ese costo es menos que el costo de crear una matriz de diez elementos que nunca termina usándose.Dicho esto, podría haber sido posible mejorar aún más el rendimiento en algunos contextos si hubiera una sobrecarga de "addAll" que especificara cuántos elementos (si los hubiera) probablemente se agregarían a la lista después de la actual, y cuáles podrían utilícelo para influir en su comportamiento de asignación. En algunos casos, el código que agrega los últimos elementos a una lista tendrá una idea bastante clara de que la lista nunca necesitará más espacio. Hay muchas situaciones en las que una lista se completa una vez y nunca se modifica después de eso. Si en el punto el código sabe que el tamaño final de una lista será de 170 elementos, tiene 150 elementos y un almacén de respaldo de tamaño 160,
fuente
addAll()
. Esa es otra oportunidad más para mejorar la eficiencia alrededor del primer malloc.La pregunta es '¿por qué?'.
Las inspecciones de perfiles de memoria (por ejemplo ( https://www.yourkit.com/docs/java/help/inspections_mem.jsp#sparse_arrays ) muestran que las matrices vacías (llenas de nulos) ocupan toneladas de memoria.
El tamaño predeterminado de 10 objetos significa que asignamos 10 punteros (40 u 80 bytes) para la matriz subyacente en la creación y los completamos con nulos. Las aplicaciones Java reales crean millones de listas de matrices.
La modificación introducida elimina ^ W pospone este consumo de memoria hasta el momento en que realmente utilizará la lista de matrices.
fuente
Después de la pregunta anterior, revisé el documento ArrayList de Java 8. Encontré que el tamaño predeterminado sigue siendo solo 10.
fuente
El tamaño predeterminado de ArrayList en JAVA 8 sigue siendo 10. El único cambio realizado en JAVA 8 es que si un codificador agrega elementos menores de 10, los lugares en blanco de la lista de arreglos restantes no se especifican como nulos. Decirlo porque yo mismo he pasado por esta situación y el eclipse me hizo investigar este cambio de JAVA 8.
Puede justificar este cambio mirando la siguiente captura de pantalla. En él puede ver que el tamaño de ArrayList se especifica como 10 en Object [10], pero el número de elementos mostrados es sólo 7. Los elementos de valor nulo en reposo no se muestran aquí. En JAVA 7, la captura de pantalla a continuación es la misma con un solo cambio, que es que los elementos de valor nulo también se muestran para los cuales el codificador necesita escribir código para manejar valores nulos si está iterando la lista completa de matrices mientras que en JAVA 8 esta carga se elimina de el jefe del codificador / desarrollador.
Enlace de captura de pantalla.
fuente