Java ArrayList. Estructura dinámica de datos

DECLARACIÓN Y CREACIÓN DE UN ARRAYLIST
De forma general un ArrayList en Java se crea de la siguiente forma:
ArrayList nombreArray = new ArrayList();
Esta instrucción crea el ArrayList nombreArray vacío.
Un arrayList declarado así puede contener objetos de cualquier tipo.
Por ejemplo:
ArrayList a = new ArrayList();
a.add("Lenguaje");
a.add(3);
a.add('a');
a.add(23.5);
Los elementos del arrayList a son:
  “Lenguaje”  2  ‘a’   23.5
Es decir, un ArrayList puede contener objetos de tipos distintos.
En este ejemplo, el primer objeto que se añade es el String “Lenguaje”. El resto no son objetos. Son datos de tipos básicos pero el compilador los convierte automáticamente en objetos de su clase envolvente (clase contenedora o wrapper) antes de añadirlos al array.
Un array al que se le pueden asignar elementos de distinto puede tener alguna complicación a la hora de trabajar con él. Por eso, una alternativa a esta declaración es indicar el tipo de objetos que contiene. En este caso, el array solo podrá contener objetos de ese tipo.
De forma general:
ArrayList<tipo> nombreArray = new ArrayList<tipo>();
tipo debe ser una clase. Indica el tipo de objetos que contendrá el array.
No se pueden usar tipos primitivos. Para un tipo primitivo se debe utilizar su clase envolvente.
Por ejemplo:
ArrayList<Integer> numeros = new ArrayList<Integer>();
Crea el array numeros de enteros.
MÉTODOS DE ARRAYLIST
Algunos métodos que proporciona ArrayList son:
MÉTODO
DESCRIPCIÓN
size()
Devuelve el número de elementos (int)
add(X)
Añade el objeto X al final. Devuelve true.
add(posición, X)
Inserta el objeto X en la posición indicada.
get(posicion)
Devuelve el elemento que está en la posición indicada.
remove(posicion)
Elimina el elemento que se encuentra en la posición indicada. Devuelve el elemento eliminado.
remove(X)
Elimina la primera ocurrencia del objeto X. Devuelve true si el elemento está en la lista.
clear()
Elimina todos los elementos.
set(posición, X)
Sustituye el elemento que se encuentra en la posición indicada por el objeto X. Devuelve el elemento sustituido.
contains(X)
Comprueba si la colección contiene al objeto X. Devuelve true o false.
indexOf(X)
Devuelve la posición del objeto X. Si no existe devuelve -1
Los puedes consultar todos en:
RECORRER UN ARRAYLIST
Podemos recorrerlo de forma clásica con un bucle for:

for(int i = 0;i<array.size();i++){
            System.out.println(array.get(i));
}

Con un bucle foreach:
Si suponemos el array de enteros llamado numeros:
for(Integer i: numeros){
           System.out.println(i);
}

Si el array contiene objetos de tipos distintos o desconocemos el tipo:
for(Object o: nombreArray){
            System.out.println(o);
}

Utilizando un objeto Iterator.
La ventaja de utilizar un Iterador es que no necesitamos indicar el tipo de objetos que contiene el array.
Iterator tiene como métodos:
hasNext: devuelve true si hay más elementos en el array.
next: devuelve el siguiente objeto contenido en el array.
Ejemplo:
ArrayList<Integer> numeros = new ArrayList<Integer>();
…..
//se insertan elementos
.....

Iterator it = numeros.iterator(); //se crea el iterador it para el array numeros
while(it.hasNext())                    //mientras queden elementos
        System.out.println(it.next());  //se obtienen y se muestran

EJEMPLOS DE USO DE ARRAYLIST
Ejemplo 1:
ArrayList<String> nombres = new ArrayList<String>();
nombres.add("Ana");
nombres.add("Luisa");
nombres.add("Felipe");
System.out.println(nombres); // [Ana, Luisa, Felipe]
nombres.add(1, "Pablo");
System.out.println(nombres); // [Ana, Pablo, Luisa, Felipe]
nombres.remove(0);
System.out.println(nombres); // [Pablo, Luisa, Felipe]
nombres.set(0,"Alfonso");
System.out.println(nombres); // [Alfonso, Luisa, Felipe]
String s = nombres.get(1);
String ultimo = nombres.get(nombres.size() - 1);
System.out.println(s + " " + ultimo);  // Luisa Felipe



Ejemplo 2: Escribe un programa que lea números enteros y los guarde en un ArrayList hasta que se lea un 0 y muestra los números leídos, su suma y su media.
import java.util.*;

public class ArrayList2 {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        ArrayList<Integer> numeros = new ArrayList<Integer>();
        int n;
        do {
            System.out.println("Introduce números enteros. 0 para acabar: ");
            System.out.println("Numero: ");
            n = sc.nextInt();
            if (n != 0)
                numeros.add(n);
        }while (n != 0);
       
        System.out.println("Ha introducido: " + numeros.size() + " números:");
       
        //mostrar el arrayList completo
        System.out.println(numeros);
       
        //recorrido usando un iterador para mostrar un elemento por línea
        Iterator it = numeros.iterator();
        while(it.hasNext())
              System.out.println(it.next());
        
        //recorrido usando foreach para sumar los elementos
        double suma = 0;
        for(Integer i: numeros){
            suma = suma + i;
        }
        System.out.println("Suma: " + suma);
        System.out.println("Media: " + suma/numeros.size());
    }
}

COPIAR UN ARRAYLIST
El nombre de un ArrayList contiene la referencia al ArrayList, es decir, la dirección de memoria donde se encuentra el ArrayList, igual que sucede con los arrays estáticos.
Si disponemos de un ArrayList de enteros llamado ventas:








La instrucción:
ArrayList<Integer> ventas1 = ventas;
No copia el array ventas en el nuevo array ventas1 sino que crea un alias:









De esta forma tenemos dos formas de acceder al mismo ArrayList: mediante la referencia ventas y mediante la referencia ventas1.
Para hacer una copia podemos hacerlo de forma manual elemento a elemento o se puede pasar la referencia del ArrayList original al constructor del nuevo:
ArrayList<Integer> ventas1 = new ArrayList<Integer>(ventas);

ARRAYLIST COMO PARÁMETRO DE UN MÉTODO
Un ArrayList puede ser usado como parámetro de un método. Además un método puede devolver un ArrayList mediante la sentencia return.
Ejemplo: Método que recibe un ArrayList de String y lo modifica invirtiendo su contenido:
import java.util.*;

public class ArrayList4 {

    public static void main(String[] args) {
        ArrayList<String> nombres = new ArrayList<String>();
        nombres.add("Ana");
        nombres.add("Luisa");
        nombres.add("Felipe");
        nombres.add("Pablo");
        System.out.println(nombres);
        nombres = invertir(nombres);
        System.out.println(nombres);
    }

    public static ArrayList<String> invertir(ArrayList<String> nombres) {
        // Crea una lista para el resultado del método
        ArrayList<String> resultado = new ArrayList<String>();
        // Recorre la lista de nombres en orden inverso
        for (int i = nombres.size() - 1; i >= 0; i--) {
             // Añade cada nombre al resultado
              resultado.add(nombres.get(i));
        }
        return resultado;
    }
}

ARRAYS BIDIMENSIONALES UTILIZANDO ARRAYLIST
Un ArrayList es un array unidimensional, pero con ellos podemos simular arrays de dos o más dimensiones anidando ArrayLists.
Para crear una matriz lo que creamos es un ArrayList cuyos elementos son a su vez ArrayList. Esto se puede extender sucesivamente y obtener arrays de más dimensiones.
Ejemplo:
Programa que lee las notas de 10 alumnos y las guarda en un ArrayList Bidimensional. Cada alumno tiene un número indeterminado de notas. La lectura de notas de cada alumno acaba cuando se introduce un número negativo. Finalmente se muestran todas las notas de todos los alumnos.

public static void main(String args[]){

        Scanner sc = new Scanner(System.in);
        final int numAlumnos = 10;  //número de alumnos
        int i, j, nota, cont = 1;
       
        //crear un ArrayList bidimensional de enteros vacío
        //Realmente se crea un ArrayList de ArrayLists de enteros
        ArrayList<ArrayList<Integer>> array = new ArrayList<ArrayList<Integer>>();
       
        //Se leen las notas de cada alumno.
        System.out.println("Introduzca notas. <0 para acabar");
        for(i=0;i<numAlumnos;i++){
            cont = 1;
            System.out.println("Alumno " + (i+1) + ": ");
            System.out.print("Nota " + cont + ": ");
            nota = sc.nextInt();

           //para cada alumno se añade una nueva fila vacía
           //esto es necesario porque el arrayList se crea vacío
            array.add(new ArrayList<Integer>());

            while(nota>=0){
                array.get(i).add(nota); //en la fila i se añade un nueva nota
                cont++;
                System.out.print("Nota " + cont + ": ");
                nota = sc.nextInt();             
            }           
        }
       
        //Mostrar todas las notas
        System.out.println("Notas de alumnos");
        for(i=0;i<array.size();i++){  //para cada alumno (para cada fila)
            System.out.print("Alumno " + i + ": ");
            for(j=0;j<array.get(i).size();j++){  //se recorre todas la columnas de la fila
                System.out.print(array.get(i).get(j) + " "); //se obtiene el elemento i,j
            }
            System.out.println();          
        }
    }

58 comentarios:

  1. Excelente muy muy bueno Gracias!!!

    ResponderEliminar
  2. Muy bueno. Gracias!!!

    ResponderEliminar
  3. exelente............

    ResponderEliminar
  4. TA WENO Y BIEN RESUMIDO, MUCHAS GRACIAS

    ResponderEliminar
  5. Muy bueno, t felicito!

    ResponderEliminar
  6. Excelente! Me ayudo bastante :D

    ResponderEliminar
  7. excelentemente excelente... go go go...

    ResponderEliminar
  8. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  9. Antes que nada felicitar por tu explicacion, ahora tengo una duda, estoy haciendo un proyecto, un programa tipico de dar alta a clientes, donde tengo un menu clientes, uqe se despliega y sale alta clientes, y edita clientes. Entonces, en alta clientes hay 3 JText, (nombre, y apellidos) y cuando clico en guardar estos datos se guardan en una array list, el problema es que cuando voy a la clase edita, me tendria que cargar la anterior array con los datos per no lo hace..

    ResponderEliminar
    Respuestas
    1. sq tienes q instanciarlos p no seas tarado fijate tus clases cn tus subclases :3 ctmr

      Eliminar
  10. muy completo este tema. justo lo que necesitaba para enseñar, saludos

    ResponderEliminar
  11. Excelente articulo, me sirvió mucho :)

    ResponderEliminar
  12. El más completo que encontré, y bien explicado! gracias salu2

    ResponderEliminar
  13. Excelente articulo, pero nose si me pueden dar una mano, deseo concatenar los valores que tengo dentro de mi arraylist, los elementos todos son string, pero cuando hago un while para recorrerlo o un for solo me graba el ultimo valor, alguien puede darme una mano?

    ResponderEliminar
    Respuestas
    1. Hola Tohure, no he entendido bien lo que quieres hacer pero si al recorrerlo te sale el último valor es posible que no hayas creado un objeto nuevo cada vez y estés trabajando siempre con el mismo.

      Eliminar
  14. muy buen artículo todo bien explicado gracias

    ResponderEliminar
  15. Respuestas
    1. Gracias Francisco, espero que te haya servido de ayuda

      Eliminar
  16. De acuerdo con Francisco Tenelema, la explicación fur muy clara. Muy buen trabajo con tu blog.
    SoftMAS Desarrollo de Software
    http://soft-mas.com

    ResponderEliminar
  17. Muy buen artículo! Gracias.

    ResponderEliminar
  18. COMO SE IMPRIME EL ULTIMO ELEMENTO EN UN ARRAYLIST.. ESPERO PUEDAN RESPONDERME

    ResponderEliminar
    Respuestas
    1. System.out.println(array.get(array.size()-1));

      Eliminar
  19. alguno de ustedes sabe como mostrar todos los datos de un array utilizando la funcion JOptionPane.showInputDialogue....???

    ResponderEliminar
    Respuestas
    1. //Puedes intentar recorriendo el array con un for y en cada iteración, acumularlo en una variable String //así:
      String salida = " ";
      for(int i = 0;i<array.size();i++){
      salida = salida + array.get(i) + " ";
      }
      //Y al final sólo le pasas de parámetro al JOption la variable salida así:
      JOptionPane.showMessageDialogue(salida);

      Eliminar
  20. Muchísimas gracias por la explicación sobre cómo copiar un ArrayList. Me estaba volviendo loco intentando enviar uno como parámetro a una instancia de clase y por alguna razón, siempre lo enviaba vacío. Haciendo el cambio se solucionó. :)

    ResponderEliminar
    Respuestas
    1. Me alegro de que te haya servido de ayuda dranzer, saludos ;)

      Eliminar
  21. Gran artículo Enrique. ¡Felicidades!

    Una duda que me surge. Al devolver el dato de un arrayList bidimensional lo haces mediante un get de otro get (array.get(i).get(j) en el ejemplo), ¿pero como harías si deseas modificar ese dato en concreto? Porque el método set de la clase ArrayList te exige un índice de tipo entero, y en caso de un arrayList bidimensional como el suyo tenemos dos índices (i y j).

    Un saludo, y reitero mi enhorabuena por el artículo.

    ResponderEliminar
    Respuestas
    1. Hola, me respondo a mí mismo porque creo que se podría hacer de este modo (a ver si me lo puedes confirmar):

      array.get(i).set(j, dato);

      Un saludo nuevamente.

      Eliminar
    2. Hola Bryan gracias por el comentario. Tienes razón con la respuesta que tu mismo te has dado a tu pregunta. Esa es la forma de hacerlo, aunque con el tiempo que ha pasado desde que hiciste la pregunta seguro que ya lo habrás descubierto. Un saludo y espero que sigas visitando el blog y dejando un comentario de vez en cuando.

      Eliminar
  22. Alguien me podria ayudar con esto?

    Según las distintas situaciones presentadas, realizar una serie de instrucciones que declaren e inicializen una variable.

    Ej. La altura maxima del puente es de 35.4 mts.

    float alt_max = 35.4;

    Según las distintas situaciones presentadas, realizar una serie de instrucciones que declaren e inicializen una variable. Seleccionar el tipo de dato para caso.

    El número de alumnos es 456.
    La empresa tiene el nombre de Curro S.A.
    El límite de velocidad es de 80 km/h
    La tarifa de importación es del 5.25 %
    Para finalizar precione el signo numeral
    No sabe
    Son 11 los jugadores
    Nuestra galaxia tiene alrededor de 100,000 millones de estrellas
    La capacidad maxima de carga es de 50,000 Kg.
    Se ha disminuido un 18% el número de accidentes.
    La distancia entre la Tierra y la Luna es de 384,400 km
    La aceleración de gravedad de 9.8 m/s2

    ResponderEliminar
    Respuestas
    1. lol facil
      int NAlumnos = 456;
      String Empresa = "Curro S.A.";
      Final int velocidad= 80;
      float importacion = 5.25; esta depende del contexto de como la utilices
      String Empresa = "Para finalizar precione el signo numeral";
      PTM Y ESTA Q
      String Empresa = "Son 11 los jugadores";
      de flojera esta te lo dejaron para q aprendas como declarar las cosas sugiero que le pongas mas lectura y menos peticion por q esto es fundamental para el entendimiento de java

      Eliminar
  23. Una pregunta.
    Estoy haciendo un programa con arraylist solo que con ventanas y cuando me cambio entre ventanas se borra la información que ya he ingresado en una ventana, no se que es lo que pueda estar pasando, Muchas gracias.

    ResponderEliminar
    Respuestas
    1. en una ventana la variable es global, necesitas pasarla como parametro o copiarla en la otra ventana para que la variable la puedas utilizar

      Eliminar
  24. Imagino que para especificar la dimensión del array se declara tal que
    ArrayList nombreArray = new ArrayList(dimension);

    ResponderEliminar
    Respuestas
    1. Los ArrayList se crean sin indicar el tamaño, al contario de lo que ocurre con los arrays estáticos que sí que hay que hacerlo. Para crear un array de int de 40 enteros hay que especificarlo:
      int [] numeros = new int[40];
      pero un arraylist se crea sin especificar el tamaño
      ArrayList numeros = new ArrayList();
      esa instrucción crea un arraylist vacío y según la documentación de Java lo crea con una capacidad inicial para 10 elementos. Es decir, el tamaño de arrayList es 0 pero tiene memoria reservada para guardar 10 elementos. Mediante add se añaden los elementos al ArrayList y si se sobrepasan los 10 elementos se aumenta la capacidad del ArrayList en otros 10 y así sucesivamente.
      Si se declara como dices: ArrayList nombreArray = new ArrayList(dimension); lo que estamos haciendo es modificar el valor inicial de 10 por el que indiquemos en dimensión con lo que podemos evitar algo las operaciones internas de reasignación de memoria.
      Espero haberte aclarado algo. Un saludo y gracias por seguir el blog

      Eliminar
  25. exelente,exelente,exelente y mas exelente

    ResponderEliminar
  26. Es bueno encontrar gente interesada en esto, buen trabajo!!

    ResponderEliminar
  27. Muy buen material, gracias!

    ResponderEliminar
  28. Excelente aporte para los que estamos empezando en java. Mil gracias

    ResponderEliminar
  29. Me ha ayudado mucho con la práctica de matrices. Muchísimas gracias

    ResponderEliminar
  30. Gracias por esta info

    ResponderEliminar
  31. Gracias, espero que os sea util y os ayude a seguir avanzando en el mundo de Java ;)

    ResponderEliminar
  32. Ayudenme, estoy en parcial :(

    ResponderEliminar
    Respuestas
    1. quisa les sirva:
      package array1;

      import java.util.ArrayList;
      import javax.swing.JOptionPane;



      public class Array1 {


      public static void main(String[] args) {
      //reeplazar
      ArrayList alist = new ArrayList ();
      String n1 = System.getProperty("line.separator");
      String entrada = JOptionPane.showInputDialog("introduce el tamaño del arreglo");

      int introducido = Integer.parseInt(entrada);

      for( int i = 0 ; i<introducido ; i++){
      String a = JOptionPane.showInputDialog(null,"Digite dato: "+(i+1)+" a ingresar: ");
      alist.add(a);
      }
      String Salida = "";
      for (int i=0; i <alist.size(); i++ ){
      System.out.println(+(i)+" "+ alist.get(i));
      Salida += "pocicion "+i+" : "+ alist.get(i) + n1;
      }
      JOptionPane.showMessageDialog(null, Salida);

      String bus = System.getProperty("line.separator");
      String entrada2 = JOptionPane.showInputDialog("introduce el elemento que va a reemplazar");
      int remplaza = Integer.parseInt(entrada2);
      String entrada3 = JOptionPane.showInputDialog("Por que elemento va a reemplazar: "+ remplaza);
      int por = Integer.parseInt(entrada3);

      alist.set(1, por);

      String Salida6 = "";
      for (int i=0; i <alist.size(); i++ ){
      System.out.println(+(i)+" "+ alist.get(i));
      Salida6 += "pocicion "+i+" : "+ alist.get(i) + bus;
      }
      JOptionPane.showMessageDialog(null, Salida6);
      }
      }

      Eliminar
  33. La memoria de computadora puede ser comparada con una calle en una ciudad. En una calle todas las casas se numeran consecutivamente con un identificador único tal que si hablamos del número 27 de la calle Córdova, podremos encontrar el lugar sin pérdida, puesto que debe haber solamente una casa con ese número y, además, nosotros sabemos que la casa estará entre las casas 26 y 28.
    Una declaración de puntero consiste en un tipo base, un * y el nombre de la variable.
    La forma general de declaración de una variable puntero es:
    Tipo *nomb_var;
    Donde:
    Tipo: cualquier tipo valido ,ya sea primitivo o definido por el usuario
    nomb_var: es el nombre de la variable de tipo apuntador.
    Los operadores de punteros
    Existen dos operadores especiales de punteros: & y *.
    El & devuelve la dirección de memoria de su operando. Por ejemplo:
    m=&cuenta;
    pone en m la dirección de memoria de la variable cuenta. Esta dirección es la posición interna de la variable en la computadora. La dirección no tiene nada que ver con el valor de cuenta. Se puede pensar en el operador & como devolviendo "la dirección de".
    El segundo operador de punteros, *, es el complemento de &. Devuelve el valor de la variable localizada en la dirección que sigue. Por ejemplo, si m contiene la dirección de memoria de la variable cuenta, entonces:
    q=*m;
    pone el valor de cuenta en q. Se puede pensar en * como "en la dirección".
    El siguiente programa ilustra un ejemplo:
    #include
    main()
    {int cuenta, q;
    int *m;
    cuenta=100;
    m=&cuenta; //m recibe la dirección de cuenta
    q=*m; //a q se le asigna el valor de cuenta
    indirectamente a través de m
    print("%d,q") //imprime 100
    }
    Punteros estáticos
    Definamos un puntero a un entero y una variable entera como sigue:
    Int *p1;
    Int valor1;
    Con estas definiciones es posible hacer las siguientes asignaciones estáticas:
    p1= *valor1;
    *p1=25;
    El apuntador p1 se define como un apuntador a un entero. La variable valor2 se define como una variable entera. La primera asignación hace que p1 apunte a la variable valor1, la segunda asignación almacena en memoria el valor 25 en donde p1 está apuntando.
    Se dice que este tipo de inicialización es de tipo estática porque la asignación de la memoria que se utiliza para almacenar es fija. Una vez definida la variable, el compilador establece suficiente memoria para almacenar un valor de un tipo dado. Esta memoria permanece reservada para esta variable y no es posible usarla para nada más hasta que se termine la función.

    ResponderEliminar