Arraylist Java: usando listas em Java!

Muitas vezes, durante o desenvolvimento de aplicações, usamos o ArrayList Java para agrupar todos os dados que queremos em estruturas para posterior utilização em nosso programa. O ArrayList é uma das principais maneiras que manipulamos listas, dicionários, filas, pilhas ou qualquer outro tipo de coleção.

Às pessoas iniciantes na linguagem — ou na programação — pode ser um tanto confuso, ainda mais com outras nomenclaturas parecidas ou funções ainda desconhecidas que permeiam a utilização do ArrayList. Na realidade, poucos são os que iniciam no Java e que sabem realmente a importância que essa estrutura tem dentro dos códigos modernos.

Sabendo disso, trazemos, neste guia, um apanhado de explicações e abordagens práticas diferentes sobre o uso do ArrayList para a linguagem Java, para ajudar quem está iniciando a entender mais sobre essa classe e sua utilização. Além disso, claro, fazer com que os mais experientes relembrem algumas questões importantes sobre as melhores práticas estabelecidas na linguagem. Abordaremos os seguintes conteúdos:

Prepare-se e vamos lá!

O que é a Arraylist Java?

O Java ArrayList, é, basicamente, um array dinâmico que encontramos no java.util — um pacote que contém uma grande variedade de recursos, como estruturas de coleções, modelos de data e hora, recursos para internacionalização, entre muitos outras facilidades para o desenvolvimento de aplicações em Java. Esses arrays redimensionáveis são muito úteis quando utilizados para implementações em que precisamos manipular listas.

A dinamicidade do recurso possibilita à pessoa desenvolvedora a criação de coleções — arrays, classes e objetos — sem precisar se preocupar com o redimensionamento dos vetores. Caso algum haja necessidade de uma posição adicional em um array, o ArrayList realiza a operação de maneira autônoma.

Quais as principais características da classe Arraylist Java?

Entre as interfaces e classes das estruturas disponibilizados para uso durante o desenvolvimento de aplicações em Java, certamente, o ArrayList é uma das principais delas. Sua característica de construção dinâmica de arrays possibilita manipulá-las com o uso de métodos para adicionar ou retirar objetos. Sua implementação é realizada usando de um array subjacente a ele.

Em outras palavras, quando adicionamos um elemento em um ArrayList, o que acontece é que a classe aloca um elemento adicional em outro vetor, maior, para posteriormente copiá-lo em um novo. Por ser custoso mover arrays manualmente, fica muito mais fácil criarmos um ArrayList com um tamanho predefinido, igual ao número que o vetor terá ao estar cheio.

Normalmente, quem trabalha com desenvolvimento não especifica um tamanho inicial para um ArrayList, apenas em casos específicos — nem sempre saberemos qual será o tamanho máximo de posições em vetor, não é mesmo?

Quais as diferenças entre array e arraylist em java?

Quando utilizamos o array em Java, estamos trabalhando com tamanhos fixos de coleções. Para inserirmos algum elemento naquele grupo de objetos, precisamos criar outro que contemple aquele novo tamanho, com determinado número de posições a mais — isso não acontece com o ArrayList.

É muito comum a confusão de que arrays e ArrayList são a mesma coisa, mas saiba que eles são muito diferentes. O ArrayList não é um array padrão, ele apenas utiliza essa funcionalidade para realizar o armazenamento dos objetos contidos nas listas manipuladas por ele. Nem ao menos os atributos desse array, que o ArrayList utiliza, é possível ser acessado durante o processamento.

Como a classe ArrayList é um agrupamento dinâmico de objetos, isso quer dizer que podemos adicionar ou retirar elementos de, por exemplo, uma lista, sem que seja necessário criar uma nova, mantendo a original com um número diferente dos objetos ali contidos. Desde o momento em que criamos um array, seu tamanho não pode ser mudado:

String [] meuStringArray = new String[3];

Repare que, nesse caso, independentemente de termos objetos ou não dentro de nosso novo array, sempre teremos para ele três posições disponíveis, nunca mais do que isso. O que é bem diferente para o ArrayList.

Aqui, trazemos um exemplo prático da aplicação:

list lista = new ArrayList();    
lista.add("Pessoa 1");      
lista.add("Pessoa 2");      
lista.add("Pessoa 3");

Isso porque a classe ArrayList é independente do número de objetos contidos nela. Podemos aumentar ou diminuir seu tamanho, apenas inserindo ou retirando mais objetos.

Qual a hierarquia da classe Arraylist?

Por serem membros de uma mesma classe, a java.util, as interfaces nas estruturas das coleções Java obedecem a uma hierarquia. Entre essas estruturas presentes nesses pacotes, algumas aparecem como as principais para o conhecimento das pessoas iniciantes nessa linguagem.

Uma coleção pode agregar vários tipos de interface. Podemos destacar conjuntos, listas (list), filas (queue) e mapas (maps). Cada uma delas pode fazer parte de uma mesma coleção, independentemente da estrutura utilizada.

A hierarquia serve para representar que cada uma dessas estruturas são de um tipo único. Explicando de outra maneira: não é possível termos uma lista e, ao mesmo tempo, termos um conjunto na mesma coleção. Por exemplo, para declararmos uma coleção, usamos a seguinte sintaxe:

Collection<String> coleção = new ArrayList();

Para adicionarmos valores nessas coleção:

import java.util.Collection;
import java.util.ArrayList;

public class MetodoAdd {
   public static void main(String[] args) {
      Collection<String> nomes = new ArrayList();
      nomes.add("João");
      nomes.add("Maria");
      nomes.add("Eduardo");
      nomes.add("Silvana");
      nomes.add("Mário");

      System.out.println(“Lista de nomes: ”+nomes);
   }
}

Explicaremos mais detalhes sobre as coleções e as interfaces de estrutura na sequência, acompanhe.

Conjuntos

Também chamada de Set Interface, essa interface não armazena dados sobre a contagem dos elementos presentes ou a ordem em que se encontram. É um arranjo de objetos que pode ser comparado às estruturas de conjunto que aprendemos nas aulas de matemática, no ensino fundamental.

Usamos o método set() para adicionar um elemento a um conjunto. Também é possível usar o método sortedset() para ordená-lo e não termos objetos repetidos nesse modelo de estrutura. 

Por exemplo, aqui, usamos uma aplicação da interface Set feita de maneira bem simples para fins didáticos. Suponha que você tenha uma Coleção, que chamaremos de “col”, e queira criar outra, contendo os mesmos elementos, mas com todas as duplicatas eliminadas. O código em uma linha ficará dessa maneira:

Collection<Type> semDuplicados = new HashSet<Type>(col);

Listas

A interface List é implementada pela classe ArrayList, fornecendo métodos para que seja possível manipular os objetos baseados na posição em que estão. Essa sequência de elementos, como também pode ser chamada, tem os índices iniciados em 0 — ou seja, o sequenciamento acontece da mesma maneira dos vetores, e começa sua contagem do 0, em vez do 1.

Nesse exemplo, vemos como podemos trocar dois valores de posição usando a interface list:

public static void swap(List a, int i, int j) {
    tmp = a.get(i);
    a.set(i, a.get(j));
    a.set(j, tmp);
}

Filas 

Na interface de estrutura de dados que chamamos fila (ou queue), a ordem de chegada de cada elemento é o que mais importa para o processamento da operação. Conforme os elementos são adicionados, são colocados no fim da fila e aguardam até que sejam acessados.

Um exemplo possível para essa interface seria a criação de um temporizador — usando a função da fila para armazenar valores e imprimi-los na saída a cada segundo, podemos criar um pequeno programa de timer de um minuto:

int relogio = Integer.parseInt(args[0]);

Queue<Integer> queue = new LinkedList<Integer>();{
  for (int i = time; i >= 0; i--)
    queue.add(i);
  } while (!queue.isEmpty()) {
        System.out.println(queue.remove());
        Thread.sleep(60);
  }

Mapas

Map é um objeto que opera armazenando chaves e valores. As chaves nunca poderão ser repetidas e sempre devem ter algum valor. Seu funcionamento pode ser comparado à abstração das funções em matemática. Essa interface utiliza métodos comuns para operar, como set(), add(), remove() etc.

Um bom exemplo de uso para a interface map seria a ordenação de cada pessoa em determinado grupo em relação à cidade em que mora:

Map<String, List<Pessoa>> pessoasPorCidade
         = pessoaColecao.collect(Collectors.groupingBy(Pessoa::getCidade));

Quais os principais métodos usados com a classe Arraylist?

Seja para adicionar algum objeto, seja para remover ou apagar todo um vetor usando a classe ArrayList, precisamos usar alguns métodos. Para facilitar o seu entendimento, listamos alguns deles com uma breve explicação de cada um. Acompanhe-os para compreender os exemplos com maior profundidade:

  • new ArrayList(): cria um novo ArrayList. Por padrão, essa classe tem a capacidade inicial de 10 elementos;
  • add(item): é o método utilizado para adicionar novos elementos ao ArrayList. Os elementos são colocados no fim da lista, por padrão;
  • remove(posição): remove um item de determinada posição na lista criada;
  • set(item, lista): usamos para definir um elemento em determinado index;
  • get(item): retorna o objeto ligado a determinado índice;
  • iterator(): responsável por iterar um elemento na sequência adequada do vetor;
  • clear(): limpa todos os elementos contidos na lista.

Confira 4 exemplos práticos de uso dos métodos!

Para entender mais sobre o assunto, vale a pena ver como funciona, na prática.

1. Criando novo ArrayList com o método new ArrayList()

import java.util.ArrayList;

public class Main {
  public static void main(String[] args) {
   ArrayList<String> carros = new ArrayList<String>();
   System.out.println(carros);
  }
}

2. Adicionando elementos como método add()

import java.util.ArrayList;

public class Main {
  public static void main(String[] args) {
   ArrayList<String> carros = new ArrayList<String>();
   carros.add("Fusca");
   carros.add("Brasília");
   carros.add("Chevette");
   carros.add("Monza");
   carros.add("Monza");
   System.out.println(carros);
   }
}

3. Apagando todo o ArrayList com o método clear()

import java.util.ArrayList;

  public class Main {
    public static void main(String[] args) {
     ArrayList<String> carros = new ArrayList<String>();
     carros.add("Fusca");
     carros.add("Kombi");
     carros.add("Brasilia");
     carros.add("Ferrari");
     carros.clear();
     System.out.println(carros);
    }
  }

Não teremos impressão de informação de nenhum carro na tela, repare que a lista é limpa com o método clear(). Teremos a impressão de algo como:

[]

4. Acessando um elemento da lista com o método get()

import java.util.ArrayList;

public class Main {
  public static void main(String[] args) {
   ArrayList<String> cars = new ArrayList<String>();
   carros.add("Fusca");
   carros.add("Kombi");
   carros.add("Brasilia");
   carros.add("Ferrari");
   System.out.println(carros.get(0));
  }
}

Aqui, teremos a impressão do nome do carro que ocupa a posição 0 de nosso ArrayList:

Fusca

Como adotar, na prática? 3 exemplos de usos da classe Arraylist

A seguir, você acompanha alguns exemplos básicos que trazemos para ilustrar tudo o que exploramos no decorrer de nosso guia. Você pode tentar replicá-los em seu computador para fixar melhor o conteúdo e praticar um pouco a implementação de um ArrayList. Vamos lá?

Exemplo 1 — listando disciplinas oferecidas em uma escola

Aqui, é possível observarmos o uso de um ArrayList com inserção de objetos (nesse caso, disciplinas escolares) com o método add(). Primeiro, criamos uma lista primária com algumas das disciplinas usando o ArrayList.

Em seguida, criamos uma ArrayList e incluímos todas as disciplinas da lista anterior, adicionando duas novas na composição:

import java.util.ArrayList;
import java.util.Arrays;

public class TesteA {
  public static void main(String[] args) {
     String[] disciplinas = {"matemática", "filosofia", "história", "física"};
     ArrayList<String> novaLista = new ArrayList<String>(Arrays.asList(disciplinas));
     novaLista.add("geografia");
     novaLista.add("língua inglesa");
    
     for (String str: novaLista)
     {
           System.out.println(str);
     }
  }
}

A saída desse código no terminal deverá ser:

matemática
filosofia
história
física
geografia
língua inglesa

Exemplo 2 — Declarando uma agenda de contatos e realizando seu instanciamento

import java.util.*;

public class Exemplo2 {

  public static void main(String[] args) {
    Scanner ler = new Scanner(System.in);
    ArrayList<String> agenda = new ArrayList();

    agenda.add("Bezerra da Silva;11 1111-1111");
    agenda.add("Paulo Ricardo;22 2222-2222");
    agenda.add("Roberto Carlos;33 3333-3333");
    agenda.add("Morais Moreira;44 4444-4444");

// mostrando os contatos a agenda:
    System.out.printf("\nPercorrendo o ArrayList)\n");
    i = 0;
    for (String contato: agenda) {
      System.out.printf("Posição %d- %s\n", i, contato);
      i++;
    }

    System.out.printf("\n Iterando o ArrayList\n");
    i = 0;
    Iterator<String> iterator = agenda.iterator();
    while (iterator.hasNext()) {
      System.out.printf("Posição %d- %s\n", i, iterator.next());
      i++;
    }
  }

}

Nesse exemplo, realizamos a iteração dos elementos contidos em nosso ArrayList mostrando todos os contatos da agenda. Repare que o método size() é utilizado para darmos um tamanho para nossa lista, definindo a quantidade de posições que ela terá.

Exemplo 3 — Ordenando a ArrayList

import java.util.*;

public class Main {
  public static void main(String[] args) {
    ArrayList<Integer> numeros = new ArrayList<Integer>();
    numeros.add(903);
    numeros.add(105);
    numeros.add(290);
    numeros.add(904);
    numeros.add(890);
    numeros.add(1902);

    Collections.sort(numeros);

    for (int i : numeros) {
      System.out.println(i);
    }
  }
}

Nesse exemplo, o que fazemos é ordenar os elementos de nossa ArrayList com a utilização do método sort(). A saída desse código será a seguinte:

105
290
890
903
904
1902

Java não genérico vs coleção genérica

Os tipos genéricos foram introduzidos a partir da versão 5 do Java, permitindo que um método seja capaz de operar sobre vários objetos de diferentes tipos. Em outras palavras, usando uma coleção genérica em Java, escreveremos uma classe, um método ou uma interface somente uma vez — e poderemos usá-los em qualquer tipo de dado.

Já se escrevermos de maneira não genérica, precisaríamos reescrever cada uma das vezes que a estrutura é utilizada. Um bom exemplo para explicar essa diferença seria supormos um ArrayList responsável pelo armazenamento de nomes de alunos de uma escola.

Se, por algum engano, o programador utiliza objetos de valores inteiros, em vez de strings, o compilador não vai proibir. Veja esse exemplo:

import java.util.*;
  
class Alunos{
    public static void main(String[] args)
    {
        //Criando um array — sem a especificação de seu tipo:
        ArrayList al = new ArrayList();
        al.add("Bob");
        al.add("Carlo");
        al.add(10);  
        
        String s1 = (String)al.get(0);
        String s2 = (String)al.get(1);
  
        try {
            //Acusa Runtime Exception:
            String s3 = (String)al.get(2);
        }
        catch (Exception e) {
            System.out.println("Exception: " + e);
        }
    }
}

Nesse caso, é um exemplo bem simples que mostra que o não uso de coleções genéricas pode causar “run time exceptions” durante sua execução — uma saída que acusa que o compilador demorou muito tempo para o processamento, de forma resumida. A saída desse código será a seguinte:

java.lang.ClassCastException:
java.lang.Integer não pode ser convertido em java.lang.String

Concluindo, a conversão de tipo individual não é necessária com o uso de coleções genéricas. Evitamos problemas futuros durante a implementação se o compilador já entender previamente que a nossa lista apenas pode usar dados do tipo string, por exemplo:

import java.util.*;
  
class Test {
    public static void main(String[] args)
    {
        //Especificamos o ArrayList como “string” desta vez:
        ArrayList<String> al = new ArrayList<String>();
  
        al.add("Bob");
        al.add("Carlo");
  
        //Agora o compilador não deixa que isso ocorra:
        al.add(10);
  
        String s1 = al.get(0);
        String s2 = al.get(1);
        String s3 = al.get(2);
    }
}

E teremos o seguinte erro na linha 15:

15: erro: nenhum método adequado encontrado para add (int)
        al.add (10);

Vimos, no decorrer deste guia, as principais aplicações para a classe Java ArrayList e suas características mais importantes quando aplicadas durante o desenvolvimento de sistemas em Java. Você pode entender as diferenças para o Array e a utilização de cada um deles para casos específicos.

Conhecemos a hierarquia estabelecida dentro do pacote java.utils e as principais interfaces de estruturas de dados ali contidas. Exploramos os métodos mais relevantes que podem ser utilizados com ArrayList e exemplificamos com aplicações práticas desses métodos.

Deu para perceber a importância da utilização de coleções genéricas e suas aplicações mais recorrentes, certo? Concluindo, passamos pelas principais características e aplicações possíveis para o Java ArrayList, com exemplos práticos que contemplem a teoria da maneira mais simples e acessível que encontramos.

Se você quer conhecer mais da linguagem Java e de seus métodos, assim como outras linguagens, não deixe de assinar nossa newsletter e receba, gratuitamente em sua caixa de entrada, as novidades que preparamos para você em nosso blog!