2012-01-19 11 views
7

preguntando si hay una manera más eficiente para agregar un elemento a ArrayList de Java en una posición más grande que su tamaño actual:Java ArrayList añadir el artículo fuera tamaño actual

Escenario:

ArrayList<Item> items = new ArrayList<Item>; 
    ... let's say I add three elements 

Ahora me gustaría para añadir un elemento en la posición 10 (dejar los artículos del 3 al 10 null)

items.add(10,newItem); // item.size() == 3 

¿hay una manera eficiente de cambio de tamaño/llenado de un ArrayList con nulos? ..

aplicación de Java hace campo de tamaño :-(privada ..

+0

Probablemente deberías utilizar HashMap u SortedMap. –

+0

Ok, usar un Mapa no es una solución para la memoria, sabemos que al final la estructura está llena -> TIntObjectHashMap (trove) quizás – ic3

+0

Un HashMap no admite el orden. Un SortedMap es una mejor opción. –

Respuesta

6

en mi humilde opinión, lo mejor que puede hacer es items.addAll(Collections.nCopies(6, null)) y Espero que ArrayList implemente algún comportamiento para fijarlo internamente.

+0

Esto es bueno pero un poco aterrador desde el punto de vista del rendimiento – ic3

+0

bien nCopies solo produce un Wrapper de lista para una matriz y de esta manera tu ArrayList puede usar el sistema .arraycopy para completar el nulo según cuán inteligente se implemente – Hachi

+1

public boolean addAll (Colección c) { \t Objeto [] a = c.toArray(); int numNew = a.length; \t ensureCapacity (size + numNew); // Incrementa el sistema ModCount .arraycopy (a, 0, elementData, size, numNew); size + = numNew; \t return numNew! = 0; } – ic3

-2

Uso constructor ArrayList(int initialCapacity) De esta manera se puede establecer una capacidad inicial

+1

InitialCapacity is not the size -> Excepción en el subproceso "main" java.lang.IndexOutOfBoundsException: Index: 9, Size: 0 – ic3

+0

Prueba : public static void main (String [] args) { ArrayList list = new ArrayList (10); list.add (9,3); } – ic3

0

Consideraría usar un SortedMap en lugar de una lista aquí. Esto permitirá que los índices no existan:

SorteMap<Integer, Item> myMap = new TreeMap<Integer, Map>(); 
int i=0; 
myMap.put(i++, first); 
myMap.put(i++, second); 
myMap.put(i++, third); 
myMap.put(10, other); 

Si un Mapa realmente no funciona, como usted indicó. Entonces sugeriría crear un Decorator alrededor de ArrayList. En el método de inserción, agregue nulos para llenar las ubicaciones vacías. Sugeriría usar el ForwardingList de Guava para facilitar la creación de la clase. De esta forma solo tendrías que implementar un método.

+0

esa no es una opción para las tomas de memoria ... – ic3

+0

¿Qué pasa con la memoria aquí? @John B: corrige este código. –

+0

TreeMap con 1mio El objeto es grande. – ic3

0

No, usted no puede hacer esto, Pero si desea hacer eso, a continuación, añadir objeto vacío en el restante índice como ..

ArrayList<Object> items = new ArrayList<Object>(); 
    items.add(new Object()); 
    items.add(new Object()); 
    items.add(new Object()); 
    items.add(3,new Object()); 
+0

en realidad estaba buscando algo un poco más elegante :-) – ic3

2

¿Qué tal esto?

ArrayList<Item> items = new ArrayList<Item>(); 

items.add(new Item(0)); 
items.add(new Item(1)); 
items.add(new Item(2)); 

items.addAll(Collections.<Item>nCopies(7, null)); 
items.add(10,new Item(10)); 

System.out.println(items); 

impresiones

[0, 1, 2, null, null, null, null, null, null, null, 10] 
+0

Usa '10 - items.size' en lugar de' 7' como una opción más robusta. –

0

Si la memoria y el índice es tan importante que utilice una matriz normales.

Cuando se trata de un uso pequeño System.arraycopy es la manera en que ArrayList lo hace interno.

-

incluso si se utiliza el ArrayList y tener un millón de objetos, es aconsejable utilizar el ArrayList (int initialCapacity) -Constructor para evitar una gran cantidad de operaciones de copia-

1

Uso TreeMap lugar. Aquí hay un ejemplo simple para verificar el consumo de memes. Ejecute la primera y la segunda prueba separadamente y use jvisualvm para verificar el tamaño del almacenamiento dinámico. Recuerde realizar GC varias veces.

public class Test { 


      public static void main(String[] args) throws InterruptedException { 
       String s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque metus."; 


       //Test 1 
       ArrayList<String> l = new ArrayList<String>(); 

       for (int i = 0; i < 1000000; i++) { 
        l.add(s + " " + i); 
        l.addAll(Collections.nCopies(i % 10, (String)null)); //Add some nulls 
       } 
       //Heap is > 5MB 

       //Test 2 uncomment and comment test 1 
    //   SortedMap<Integer, String> map = new TreeMap<Integer, String>(); 
    //   for (int i = 0; i < 1000000; i++) { 
    //    map.put(i,s + " " + i); 
    //   } 
       //Heap is < 5MB 

       Thread.sleep(100000); 

      } 
    } 

Parece que TreeMap versión es aún menor consumo de memoria que la versión ArrayList. Compruébalo.

+0

Peter, ArrayList es una matriz y poco más. ¿Cómo es posible que una matriz completa tenga más tamaño que cualquier otra estructura? ... Creo que su ejemplo tiene un problema (estoy seguro) – ic3

+0

Estamos hablando de una matriz completa .. – ic3

+0

La matriz es (s - string, n-null): snsnnsnnnsnnnnsnnnnsnnnnnnsnnnnnnns ... etc Hay mucho de la memoria reservada para las referencias pero establecida en nulo. TreeMap no tiene este problema. Como dijiste, es una matriz. Incluso una matriz de 1 millón de nulos sigue costando memoria. Se trata de qué tan "densa" es su lista. –

0

@ icCube: dijiste que esa lista debería estar llena en un 90%. Mi idea de esta solución es:

  • Si usted sabe exactamente el tamaño del objetivo - usar array plano
  • Si usted está enterado de tamaño objetivo - el uso ArrayList con capacidad inicial tan cerca como sea posible orientar tamaño. Ponga nulls con l.addAll(Collections.nCopies(n, (String)null)); como decía la gente.
  • Si no conoce el tamaño de destino, su ArrayList se redimensionará varias veces. Cambiar el tamaño significa copiar toda la matriz subyacente (usa Arrays.copyOf). Puedes imaginar lo que sucede si se copia una matriz: GC tiene mucho trabajo. Usa TreeMap entonces.
Cuestiones relacionadas