2010-03-23 45 views
14

Se sabe que Java ArrayList se implementa mediante matrices e inicializa con una capacidad de 10 y aumenta su tamaño en un 50%. Cómo obtener la capacidad actual de ArrayList, no el tamaño de ArrayList.¿Cómo obtener la capacidad de ArrayList en Java?

Thx

+3

¿Por qué necesita esta información? –

+1

Corteza ... Nada específico ... Lo tuve en una entrevista – JavaUser

+0

Google me llevó hasta aquí. La razón por la que necesito esta información: tengo una ArrayBlockingQueue que me permite tomar, procesar y almacenar resultados en otra Colección. Pensé que sería bueno usar una capacidad inicial para la Colección de resultados que coincida con la capacidad del ABQ. No es un caso de uso tan extraño, ¿no? Hay otras formas de evitarlo (por ejemplo, almacenar la capacidad como una final estática y hacer referencia a eso), pero no necesariamente en todos los casos. – ericsoco

Respuesta

16

No creo que esto sea posible. ¿Cuál es tu caso de uso? Creo que C# ArrayLists tiene una propiedad .capacity, pero la clase Java ArrayList no expone esta información.

Tiene el constructor que toma un argumento de capacidad inicial, y tiene el método ensureCapacity() que puede usar para reducir la cantidad de reasignación incremental.

También tiene el método trimToSize() que puede usar si está realmente preocupado por el uso de la memoria.

+1

¿Cuál es el mismo caso con respecto a los vectores? – JavaUser

+3

Vector tiene un método de capacidad() que devuelve la capacidad actual. ¿Te has tomado el tiempo de mirar la API? http://java.sun.com/j2se/1.4.2/docs/api/java/util/Vector.html –

+2

No mbaird, solo estoy buscando su respuesta.Thx – JavaUser

0

No lo recuerde si lo tiene pero puede hacerlo usted mismo mirando el código fuente de ArrayList. Los desarrolladores de Java deben aprovechar el código fuente incluido con el SDK.

+0

No estoy seguro de qué tan útil sería esto para ayudarlo a encontrar la capacidad actual en tiempo de ejecución. A menos que tomara la fuente y agregara un método para exponer la capacidad, y luego usara su versión personalizada de ArrayList en todas partes. –

+0

Jaja, primero en la vociferación luego en el otro :): le di una varilla pero le diste un pez ... ¿Ahora qué, va a preguntar por Vector, LinkedList ...? :)) – instcode

+0

@mbaird 'podrías hacerlo tú mismo' probablemente significaba 'puedes averiguar si hay una manera de obtener la capacidad mirando el código fuente', no 'puedes cambiar el código fuente'. – bjornars

0

Acabo de ver la documentación del sol en la clase ArrayList, y el único método que vi relacionado con la capacidad fue ensureCapacity (int minCapacity), que no es exactamente lo que quieres. ¡Buena suerte!

2

En cuanto a ArrayList's spec No veo ningún método que proporcione esta información.

Dicho esto, el método ensureCapacity parece como un paso en la dirección correcta (precaución: es no garantiza una respuesta correcta): Cuando lo llamó asegura que la capacidad es de al menos el argumento especificado. Entonces, si la implementación ArrayList usa este método para asegurar la capacidad (en lugar de llamar a algún método privado/manipular directamente los campos relevantes) puede obtener la capacidad actual anulando este método. También debe sobrescribir trimToSize() de manera similar.

Por supuesto, esta solución no es muy portátil como una implementación diferente de ArrayList (en una JVM de otro proveedor) puede hacer las cosas de manera diferente.

Así es como el código debe ser similar

public class CapacityTrackingArrayList<T> extends ArrayList<T> { 

    // declare a constructor for each ArrayList constructor ... 


    // Now, capacity tracking stuff: 
    private int currentCapacity = 10; 

    public int getCapacity() { return currentCapacity; } 

    public void ensureCapacity(int arg) { 
    currentCapacity = arg; 
    super.ensureCapacity(arg); 
    } 

    public void trimToSize() { currentCapacity = size(); super.trimToSize(); } 

} 
+1

ensureCapacity() simplemente asegura que tiene al menos ese espacio. Si tiene más espacio, no hará nada. Si más tarde sigues agregando elementos para que necesite aún más, crecerá. Ninguno de estos casos sería manejado por su código de ejemplo. Todo lo que hará su código es permitirle que le recuerde qué valor pasó para garantizar la capacidad() anteriormente, lo que puede no tener ninguna relación real con lo que es la capacidad verdadera más adelante. –

+0

Por supuesto, no digo que esta sea una solución perfecta ni portátil. Es solo un paso en la dirección correcta. –

6

Se puede conseguir mediante la reflexión:

public abstract class ArrayListHelper { 

    static final Field field; 
    static { 
     try { 
      field = ArrayList.class.getDeclaredField("elementData"); 
      field.setAccessible(true); 
     } catch (Exception e) { 
      throw new ExceptionInInitializerError(e); 
     } 
    } 

    @SuppressWarnings("unchecked") 
    public static <E> int getArrayListCapacity(ArrayList<E> arrayList) { 
     try { 
      final E[] elementData = (E[]) field.get(arrayList); 
      return elementData.length; 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 

    } 
} 
+4

Esto fallará horriblemente cuando el campo no se llame 'elementData'. Y dado que ese nombre no está especificado en la API, cualquier implementación (¡y cualquier versión!) Es libre de llamarlo de otra manera. –

+0

@JoachimSauer todavía se llamaba elementData, no veo por qué cambiarían eso, ¡aún puedes modificar el código fácilmente si/cuando lo hacen! – BaSsGaz

0

Puede utilizar vectorial en lugar de ArrayList. Vector es compatible con el método capacity().

+3

El OP claramente quería la capacidad de un 'ArrayList', no un' Vector'. – Manuel

+0

Vector puede lograr lo mismo que ArrayList. Es culpa de Java no exponer la capacidad. ¿Cómo puede decidir cuándo llamar a trimtosize si no conoce la capacidad? No es eficiente llamar trimtosize todo el tiempo. En tal situación, cambiar para usar Vector es una gran idea. – jack

0

capacidad predeterminada de ArrayList es 10.Una vez que se alcanza el tamaño máximo, la nueva capacidad será:

nueva capacidad = (currentcapacity * 3/2) 1.

0

El objetivo de utilizar ArrayList es agregar dinámicamente nuevo elemento, por lo que no hay un método específico para obtener la capacidad de ArrayList.

Cada vez que agreguemos un elemento causa reasignación dinámica y la reasignación es costosa en términos de tiempo, evitar la reasignación mejora el rendimiento y por lo tanto puede aumentar manualmente la capacidad de ArrayList llamando a ensureCapacity() pero nuevamente no puede encontrar el capacidad de ArrayList

0

Este código utiliza la reflexión para obtener la capacidad de un ArrayList:

package examples1; 

import java.util.ArrayList; 
import java.util.List; 
import java.lang.reflect.Field; 

public class Numbers { 

    public static void main(String[] args) throws Exception { 
     List<Integer> numbers = new ArrayList<>(); 
     numbers.add(1); 
     System.out.println(getCapacity(numbers)); 
    } 

    static int getCapacity(List al) throws Exception { 
     Field field = ArrayList.class.getDeclaredField("elementData"); 
     field.setAccessible(true); 
     return ((Object[]) field.get(al)).length; 
    } 
} 

Esta es la salida: 10

Notas:

  1. getCapacity() método modificado del original en http://javaonlineguide.net/2015/08/find-capacity-of-an-arraylist-in-java-size-vs-capacity-in-java-list-example.html
  2. Tenga en cuenta que la capacidad predeterminada de 10 se concede después de la primera adición a la lista. Si intenta esto antes de añadir, obtendrá una producción de 0
  3. Para forzar una capacidad sin agregar, pasarlo en el constructor de este modo:

    List<Integer> numbers = new ArrayList<>(20); 
    
Cuestiones relacionadas