JavaRush /Blog Java /Random-ES /new ArrayList(????) cómo y dónde es mejor inicializar
Vovan
Nivel 22

new ArrayList(????) cómo y dónde es mejor inicializar

Publicado en el grupo Random-ES
Escribir código sin utilizar el marco de colecciones sería una locura. Esta es una maravillosa pieza de Java con muchas soluciones interesantes. Más importante aún, a diferencia de las matrices, no tienes que preocuparte por los tamaños. ArrayList crecerá hasta que se quede sin memoria. El desarrollador no tiene que preocuparse por el tamaño inicial y el error ArrayIndexOutOfBoundsException . Pero, ¿qué pasa si existe una condición para controlar la cantidad de memoria? ¿Podemos usar la memoria de manera eficiente cuando trabajamos con colecciones?
Surge una pregunta estándar: ¿cómo inicializar una lista? El siguiente código no funcionará: generará un error de compilación: Es posible que los nombres de las variables locales no se hayan inicializado . La especificación de Java requiere que todas las variables locales (las que existen en la pila) se inicialicen con los valores apropiados. Así es como puedes hacerlo: Sin duda la lista debe estar inicializada. Puede crear la lista en la primera línea o puede hacer algo más inteligente y utilizar la inicialización diferida como hicimos en el método getAllNames() . En este caso, la lista sólo se creará cuando sea necesario; si no se cumplen las condiciones iniciales, la lista nunca aparecerá en el montón. Aquí llegamos a la pregunta principal: ¿qué tamaño debemos establecer para la lista? La mejor opción es darle el tamaño exacto. Por ejemplo: en este caso, se deben devolver exactamente n nombres y, como consecuencia, se crea una colección de n elementos. Sin embargo, no siempre se conoce el valor exacto de n . Incluso en el ejemplo dado, ¿qué pasaría si n=1000 y solo hubiera 100 nombres disponibles? Cuando se trabaja con colecciones, el método más popular es llamar al constructor predeterminado. Si miras el código fuente de Java (versión 1.6) como puedes ver, por defecto se crea una lista de 10 elementos . Es decir, podemos utilizar con seguridad el constructor predeterminado cuando no planeamos almacenar más de 10 elementos en la lista. ¿Qué sucede si intentas agregar el undécimo elemento? Bueno, nada malo... el elemento se agregará exitosamente. Mire el método: el tamaño de la matriz está controlado por el método sureCapacity . El tamaño aumenta 1,5 veces . Se crea una nueva matriz y los elementos se mueven a ella. Si establecemos el tamaño en 10, entonces en el undécimo elemento:
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); } }
  • el tamaño cambia a 10 * 3 / 2 + 1 = 16
  • siguiente aumento = 16 * 3 / 2 + 1 = 25
  • siguiente aumento = 25 * 3/2 + 1 = 39 y así sucesivamente.
En el caso de 100 elementos, la JVM deberá crear una nueva matriz varias veces y copiar los elementos en ella. Teniendo esto en cuenta, si existe una suposición sobre el tamaño requerido de la matriz, es mejor establecer la capacidad inicial cerca de él. A continuación se ofrecen algunas pautas de actuación:
  1. Cree una colección solo cuando la necesite ; de ​​lo contrario, inicialícela como nula o use Collections.EMPTY_LIST .
  2. Si conoce el tamaño exacto requerido , especifíquelo en el constructor de la colección.
  3. Si está seguro de que la cantidad de elementos no excederá los 10 , no dude en utilizar el constructor predeterminado.
  4. El riesgo asociado con la creación de una colección de tamaño cero es que la frecuencia de creación de nuevas matrices y copia de datos puede ser mayor. Debe pensar con mucho cuidado si el beneficio de utilizar colecciones de tamaño cero es realmente tan grande .
  5. Si inicializó una colección demasiado grande al comienzo del método y desea reducirla, existe el método trimToSize() .
Por supuesto, estas pautas se aplican cuando se trabaja con colecciones basadas en matrices, y nada de esto tiene sentido en el caso de una lista vinculada. De hecho, es poco probable que estos problemas acaben con el programa, pero si existe la oportunidad de hacerlo un poco mejor, ¿por qué no utilizarlo? ¿Tiene algún otro consejo útil? ¿Ha encontrado formas de hacer que las cosas funcionen mejor? ¿O es todo esto innecesario? ¿Qué opinas?
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION