Home Coleções de dados em Java
Post
Cancelar

Coleções de dados em Java

Baseado nos cursos da Softblue

Arrays

  • Arrays são utilizados para agrupar dados de um mesmo tipo

Em Java, array é um objeto

1
2
3
4
int[] distancias;
distancias = new int[8]; //Array de int com 8 posições

double[] notas = new double[5]; //Array de double com 5 posições

O array é alocado no heap, inicializado e indexado de 0 ao seu (tamanho-1). Acessos fora deste intervalo resultam em erro.

  • Não é possível declarar arrays com tamanho negativo

  • Arrays podem ter tamanho 0

Formas de inicializar os arrays:

1
2
3
4
int[] array = new int[5];
int array[] = new int[5];
int[] array = { 1, 2 };
int[] array = new int[]{ 1, 2 };

Arrays de referências

  • Além de tipos primitivos, arrays também podem guardar referências a objetos
1
Cadeira[] cadeiras = new Cadeira[5];
  • Neste caso, cada posição do array referencia um objeto armazenado no heap

Percorrendo arrays

  • Utilizando o fora
1
2
3
4
5
int[] array = new int[10];
for(int i = 0; i < array.length; i++) {
	System.out.println(array[i]);
}

  • Utilizando o enhanced-fora
1
2
3
4
5
int[] array = new int[10];
for(int i : array) {
	System.out.println(i);
}

Desvantagens dos Arrays

  • Depois de criado, não é possível modificar o tamanho de um array

  • Dificuldade em encontrar elementos dentro do array quando o índice não é conhecido

  • Ao remover elementos, sobram “buracos” no array

Varargs

  • O uso de varargs permite que métodos possam receber um número variável de parâmetros
1
2
3
4
public int somar(int... valores) {
	...
}

  • Os parâmetros passados via varargs são lidos como como arrays
1
2
3
4
5
6
7
8
public int somar(int... valores) {
	int soma = 0;
	for (int valor : valores) {
		soma += valor;
	}
	return soma;
}

  • É possível passar o parâmetro diretamente como um array
1
2
3
int[] array = { 10, 20, 30 };
somar(array);

  • Parâmetros do tipo varargs podem ser misturados com parâmetros “normais”

  • Parâmetros varargs devem ser sempre os últimos definidos no método

1
2
3
4
public void metodo(int x, boolean y, String... params) {
	...
}

A Collections API

  • Possui um conjunto de classes e interfaces para facilitar o trabalho com coleções de dados

– Listas

– Conjuntos

– Mapas

Listas

  • Permitem elementos duplicados

  • Mantêm ordenação específica entre os elementos

  • Representadas pela interface java.util.List

ArrayList

  • É a implementação de listas mais utilizada

  • Trabalha internamente com um array

1
List l = new ArrayList();
  • Usando o método add(), podemos adicionar elementos no fim da lista ou em uma posição qualquer
1
2
3
4
List lista = new ArrayList();
lista.add("José");
lista.add("João");
lista.add(1, "Maria");

A lista cresce conforme o necessário

  • O método size() retorna o tamanho da lista

  • O método get() retorna o elemento da posição especificada

  • Todas as coleções são genéricas

  • Trabalham apenas com tipos Object

  • É preciso fazer casting da referência ao obter um elemento

1
String nome = (String) lista.get(1);

Percorrendo Listas

  • Usando o iterator:
1
2
3
4
5
Iterator iter = lista.iterator();
while(iter.hasNext()) {
	String nome = (String) iter.next();
	...
}
  • Usando o enhanced-for?
1
2
3
4
for(Object obj : lista) {
	String nome = (String) obj;
	...
}

Usando Generics com Listas

  • Permite restringir os tipos de dados em coleções

  • Vantagens

– Evita casting, que pode ser feito de forma errada

– Faz a verificação do tipo de dado em tempo de compilação

1
2
3
4
5
List<String> lista = new ArrayList<String>(); //Determina o tipo de dado dos elementos da coleção
List<String> lista = new ArrayList<>(); //Usando diamond
lista.add("texto"); //OK
lista.add(1); //Erro de compilação
String s = lista.get(1); //O casting não é necessário
  • Iterar sobre listas que usam generics é mais simples
1
2
3
4
5
6
7
8
9
10
Iterator<String> iter = lista.iterator();

while(iter.hasNext()) {
	String nome = iter.next();
	...
}

for(String nome : lista) {
	...
}

Ordenação de Listas

  • A ordenação possibilita que os elementos fiquem posicionados de acordo com algum critério

  • A classe Collections traz um método estático sort() para fazer ordenação de listas

  • A ordenação só funciona em um dos seguintes casos:

– Se os elementos da coleção implementarem a interface java.lang.Comparable

– Se um java.util.Comparator for utilizado

  • A utilização de uma dessas interfaces obriga o programador a implementar a regra de como os elementos serão ordenados

Listas Imutáveis

  • Lista que não pode sofrer alteração de elementos

  • A partir do Java 9 existe uma forma simples de criar essas listas

1
List<Integer> l = List.of(1, 2, 3, 4); // Qualquer quantidade de elementos

Conjuntos

  • Representam conjuntos como na matemática

  • Não permitem elementos duplicados

  • A ordem dos elementos no conjunto pode não ser a mesma da ordem de inserção

  • Representados pela interface java.util.Set

HashSet

  • Implementação de conjunto que não possui nenhuma garantia com relação à ordem dos elementos
1
2
3
4
5
6
Set conjunto = new HashSet();
conjunto.add("A");
conjunto.add("G");
conjunto.add("C");
conjunto.add("F");
conjunto.add("F");// Os elementos duplicadossão ignorados

LinkedHashSet

  • Garante que, ao iterar sobre os elementos, a ordem de iteração será a mesma da inserção
1
2
3
4
5
Set conjunto = new LinkedHashSet();
conjunto.add("A");
conjunto.add("G");
conjunto.add("C");
conjunto.add("F");

TreeSet

  • Os elementos são ordenados por algum critério no momento em que são inseridos no conjunto

  • O critério é definido como nas listas

– Implementação da interface java.lang.Comparable

– Uso de um java.util.Comparator

1
2
3
4
5
6
7
Set conjunto = new TreeSet();
conjunto.add("A");
conjunto.add("G");
conjunto.add("C");
conjunto.add("F");
//Os elementos são ordenados em ordem alfabética
//A classe String implementa a interface Comparable e define este comportamento

Distinção de elementos

  • Conjuntos não armazenam objetos iguais

– Mas como especificar quais objetos são iguais?

  • Dois métodos devem ser implementados por classes cujos objetos são usados em conjuntos

equals()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Linguagem {
	private String nome;
	private String descricao;
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Linguagem other = (Linguagem) obj;
		if (nome == null) {
			if (other.nome != null)
				return false;
		} else if (!nome.equals(other.nome))
			return false;
		return true;
	}
}

hashCode()

1
2
3
4
5
6
7
8
9
10
11
12
public class Linguagem {
	private String nome;
	private String descricao;

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((nome == null) ? 0 : nome.hashCode());
		return result;
	}
}
  • Métodos pertencem à classe Object

  • A implementação da classe Object compara referências de memória

  • Regras teóricas

– Se dois objetos são iguais, devem ter o mesmo hash code

– Se dois objetos são diferentes, podem ou não ter o mesmo hash code

  • Regras práticas

– Ambos os métodos funcionam juntos

  • Sobrescreva ambos ou nenhum

– Use o mesmo critério de igualdade na implementação de ambos os métodos

Percorrendo Conjuntos

  • Conjuntos não são indexados

  • Podem ser utilizados o iterator ou o enhanced-for

1
2
3
4
5
6
7
8
9
Iterator<String> iter = conjunto.iterator();
while(iter.hasNext()) {
	String nome = iter.next();
	...
}

for(String nome : conjunto) {
	...
}

Usando Generics com Conjuntos

  • O generics também pode ser utilizado com conjuntos do mesmo modo como é feito com as listas
1
Set<String> conjunto = new HashSet<String>();

Conjuntos Imutáveis

  • Conjunto que não pode sofrer alteração de elementos

  • A partir do Java 9 existe uma forma simples de criar esses conjuntos

1
Set<String> s = Set.of("A", "B", "C"); //Qualquer quantidade de elementos

Mapas

  • Utilizados quando é necessário mapear uma chave a um valor

  • Chaves e valores podem ser qualquer tipo de objeto

  • Representados pela interface java.util.Map

HashMap

  • Implementação de mapa que não possui nenhuma garantia com relação à ordem das chaves

  • Os métodos put() e get() podem ser usados para adicionar e obter elementos do mapa, respectivamente

1
2
3
4
5
6
7
8
ContaCorrente c1 = new ContaCorrente(123);
ContaCorrente c2 = new ContaCorrente(321);

Map contasMap = new HashMap(); //associação entre clientes e contas
contasMap.put("cliente1", c1);
contasMap.put("cliente2", c2);

ContaCorrente c = (ContaCorrente) contasMap.get("cliente1"); // O get() obtém o valor associado à determinada chave
  • O generics também pode ser usado em mapas
1
Map<String, ContaCorrente> contasMap = new HashMap<String, ContaCorrente>();

TreeMap

  • As chaves dos elementos são ordenadas por algum critério no momento em que estes são inseridos no mapa

  • O critério é definido como nas listas

– Implementação da interface java.lang.Comparable

– Uso de um java.util.Comparator

Mapas: retornando Coleções

  • A interface java.util.Map possui métodos para retornar sua lista de chaves e de valores, e até cada entrada chave/valor do mapa
1
2
3
letrasMap.keySet(); //Retorna um Set com as chaves do mapa
letrasMap.values(); //Retorna uma Collection com os valores do mapa
letrasMap.entrySet(); //Retorna um Set de objetos Map.Entry

Mapas Imutáveis

  • Mapa que não pode sofrer alteração de elementos

  • A partir do Java 9 existe uma forma simples de criar esses mapas:

1
2
3
4
5
6
7
Map<Integer, String> m = Map.of(1, "A", 2, "B", 3, "C");

Map<Integer, String> m = Map.ofEntries(
	Map.entry(1, "A"), 
	Map.entry(2, "B"), 
	Map.entry(3, "C")
); 
Esta postagem está licenciada sob CC BY 4.0 pelo autor.