0% acharam este documento útil (0 voto)
4 visualizações

Aula_38__Java_Collections

A aula 38 aborda as coleções em Java, destacando a classe ArrayList e suas alternativas como LinkedList e Set. O documento explora a importância de programar para interfaces, utilizando List em vez de implementações específicas, e discute como evitar elementos duplicados usando HashSet e ordenar elementos com TreeSet. Além disso, menciona a implementação da interface Comparable para permitir a ordenação de objetos, exemplificando com a classe Aluno.
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
4 visualizações

Aula_38__Java_Collections

A aula 38 aborda as coleções em Java, destacando a classe ArrayList e suas alternativas como LinkedList e Set. O documento explora a importância de programar para interfaces, utilizando List em vez de implementações específicas, e discute como evitar elementos duplicados usando HashSet e ordenar elementos com TreeSet. Além disso, menciona a implementação da interface Comparable para permitir a ordenação de objetos, exemplificando com a classe Aluno.
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 11

Aula 38 - Java Collections

Até o momento, trabalhamos apenas com a classe ArrayList para lidarmos com coleções
de objetos de mesmo tipo.

Entretanto, o Java possui diversas outras collections, que veremos na aula de hoje.

Os filhos de java.util.List
A classe ArrayList foi bastante usada até o momento. Com ela, podemos realizar
diversas operações.

Vamos considerar um ArrayList de alunos do nosso sistema de biblioteca. Podemos


adicionar quantos alunos quisermos. Aqui, usaremos uma classe de teste apenas para que
possamos também a api do JUnit, mas poderíamos ter usado uma classe com método main
também:

@Test
void testeDeUsoDeArrayList() {
Aluno claudiaDaSilva = new Aluno("Claudia da Silva", "550444",
"1TDSPY");
Aluno fernandoFerreira = new Aluno("Fernando Ferreira", "551088",
"1TDSPY");
Aluno joaoSantos = new Aluno("João Santos", "654032", "1TDSPY");

ArrayList<Aluno> alunos = new ArrayList<>();


alunos.add(fernandoFerreira);
alunos.add(claudiaDaSilva);
alunos.add(joaoSantos);
}

Podemos também usar diversos métodos dessa collection, em busca de informações


importantes:

assertEquals(3, alunos.size());
assertEquals(fernandoFerreira, alunos.get(0));

assertTrue(alunos.contains(fernandoFerreira));
alunos.remove(fernandoFerreira);
assertFalse(alunos.contains(fernandoFerreira));
alunos.add(fernandoFerreira);

Domain Driven Design - Prof. Rodrigo Vieira [email protected]


assertFalse(alunos.isEmpty());

Podemos também obter uma sublista da lista existente:

ArrayList<Aluno> subLista = alunos.subList(0, 1);

Mas espere! O código acima não compila:

A mensagem de erro do IntelliJ indica uma tal de List<Aluno> e informa que não
consegue converter o retorno de método (que é um List<Aluno>) para um
ArrayList<Aluno>.

Por que isso acontece?

List é uma interface, e é implementada por ArrayList:

É possível verificar isso também no código Java:

public class ArrayList<E> extends AbstractList<E>


implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{

Domain Driven Design - Prof. Rodrigo Vieira [email protected]


Mas List também é implementada por outras classes, como a LinkedList:

Há também outras classes. Veja esse link para conhecer todas elas, e para que elas
servem.

Vamos buscar entender essas implementações:

● enquanto ArrayList usa uma lista simples de elementos, LinkedList usa uma
lista duplamente ligada, onde os elementos conhecem diretamente respectivamente
seus antecessores e sucessores. Isso faz com que LinkedList seja mais eficiente
na remoção e na adição de elementos no meio da lista
● ArrayList ocupa menos espaço em memória, pois não precisa armazenar
referências de antecessores e sucessores

Podemos então, dependendo da situação, usarmos o LinkedList no nosso código.


Abaixo, um exemplo do teste exemplificado acima, mas usando LinkedList no lugar:

@Test
void testeDeUsoDeLinkedList() {
Aluno claudiaDaSilva = new Aluno("Claudia da Silva", "550444",
"1TDSPY");
Aluno fernandoFerreira = new Aluno("Fernando Ferreira", "551088",
"1TDSPY");
Aluno joaoSantos = new Aluno("João Santos", "654032", "1TDSPY");

LinkedList<Aluno> alunos = new LinkedList<>();


alunos.add(fernandoFerreira);
alunos.add(claudiaDaSilva);
alunos.add(joaoSantos);

assertEquals(3, alunos.size());

Domain Driven Design - Prof. Rodrigo Vieira [email protected]


assertEquals(fernandoFerreira, alunos.get(0));

assertTrue(alunos.contains(fernandoFerreira));
alunos.remove(fernandoFerreira);
assertFalse(alunos.contains(fernandoFerreira));
alunos.add(fernandoFerreira);

assertFalse(alunos.isEmpty());
LinkedList<Aluno> subLista = alunos.subList(0, 1);
}

De qualquer forma, a última linha continua dando erro de compilação.


Para resolvermos isso de uma vez, teremos que recorrer a aulas anteriores.

Vimos recentemente o diagrama abaixo:

Domain Driven Design - Prof. Rodrigo Vieira [email protected]


É possível notar que:
● A interface Correios é implementada por CorreiosViaCep
● A interface RepositorioAlunos é implementada por AlunoDAO

Também comentamos que, se precisar:


● podemos trocar a classe CorreiosViaCep por outra sem problemas, desde que
essa outra classe também implementasse a interface Correios
● o mesmo para AlunoDAO

Dessa forma, a alteração no projeto como um todo será mínima, apenas em poucas
classes. Os demais códigos não sofrerão alterações.

Parece que programarmos dessa forma pode ser uma boa alternativa. Ela nos garante
menos alterações no nosso sistema. Elas vão acontecer. Mas se seguirmos essa maneira
de organizar o código, elas serão menores.

Se analisarmos o código de AlunoService, podemos ver que ele não conhece as


implementações de RepositorioAlunos, muito menos de Correios. Ele conhece apenas as
interfaces.

public class AlunoService {


private Mensageiro mensageiro;
private Correios correios;
private RepositorioAlunos repositorioAlunos;

public AlunoService(Mensageiro mensageiro, Correios correios,


RepositorioAlunos repositorioAlunos) {
this.mensageiro = mensageiro;
this.correios = correios;
this.repositorioAlunos = repositorioAlunos;
}

public void adicionar(Aluno aluno) {


Endereco endereco =
correios.buscarEnderecoPor(aluno.lerCep());
aluno.atualizarEndereco(endereco);
mensageiro.enviarMensagemDeBoasVindasPara(aluno);
repositorioAlunos.adicionar(aluno);
repositorioAlunos.fechar();
}
}

AlunoService é o cliente dessas interfaces. E ele não conhece as implementações


delas, reduzindo também as suas dependências.

Domain Driven Design - Prof. Rodrigo Vieira [email protected]


Essa maneira de escrever código é conhecida por "programe para uma interface, e não
para uma implementação".

Assim, no caso dos nossos testes, podemos seguir a maneira com que o AlunoService
foi criado, fazendo com que ArrayList e LinkedList sejam cada vez menos usados,
substituindo-os quando puder pela interface List.

O código ficará assim:


@Test
void testeDeUsoDeListEArrayList() {
Aluno claudiaDaSilva = new Aluno("Claudia da Silva", "550444",
"1TDSPY");
Aluno fernandoFerreira = new Aluno("Fernando Ferreira", "551088",
"1TDSPY");
Aluno joaoSantos = new Aluno("João Santos", "654032", "1TDSPY");

List<Aluno> alunos = new ArrayList<>();


alunos.add(fernandoFerreira);
alunos.add(claudiaDaSilva);
alunos.add(joaoSantos);

assertEquals(3, alunos.size());
assertEquals(fernandoFerreira, alunos.get(0));

assertTrue(alunos.contains(fernandoFerreira));
alunos.remove(fernandoFerreira);
assertFalse(alunos.contains(fernandoFerreira));
alunos.add(fernandoFerreira);

assertFalse(alunos.isEmpty());
List<Aluno> subLista = alunos.subList(0, 2);

assertEquals(2, subLista.size());
assertTrue(subLista.contains(claudiaDaSilva));
assertTrue(subLista.contains(joaoSantos));
}

@Test
void testeDeUsoDeListELinkedList() {
Aluno claudiaDaSilva = new Aluno("Claudia da Silva", "550444",
"1TDSPY");
Aluno fernandoFerreira = new Aluno("Fernando Ferreira", "551088",
"1TDSPY");
Aluno joaoSantos = new Aluno("João Santos", "654032", "1TDSPY");

List<Aluno> alunos = new LinkedList<>();

Domain Driven Design - Prof. Rodrigo Vieira [email protected]


alunos.add(fernandoFerreira);
alunos.add(claudiaDaSilva);
alunos.add(joaoSantos);

assertEquals(3, alunos.size());
assertEquals(fernandoFerreira, alunos.get(0));

assertTrue(alunos.contains(fernandoFerreira));
alunos.remove(fernandoFerreira);
assertFalse(alunos.contains(fernandoFerreira));
alunos.add(fernandoFerreira);

assertFalse(alunos.isEmpty());
List<Aluno> subLista = alunos.subList(0, 2);

assertEquals(2, subLista.size());
assertTrue(subLista.contains(claudiaDaSilva));
assertTrue(subLista.contains(joaoSantos));
}

Como lidar com elementos duplicados? a interface


java.util.Set
Podemos também trabalhar com elementos repetidos dentro de uma coleção. Veja o
exemplo abaixo:

@Test
void testeDeUsoDeSet() {
Aluno claudiaDaSilva = new Aluno("Claudia da Silva", "550444",
"1TDSPY");
Aluno fernandoFerreira = new Aluno("Fernando Ferreira", "551088",
"1TDSPY");
Aluno joaoSantos = new Aluno("João Santos", "654032", "1TDSPY");

List<Aluno> alunos = new ArrayList<>();


alunos.add(fernandoFerreira);
alunos.add(claudiaDaSilva);
alunos.add(joaoSantos);
alunos.add(fernandoFerreira);
}
Repare que o aluno Fernando Ferreira foi adicionado 2 vezes na lista. E isso pode
acontecer em sistemas reais, acidentalmente ou não.

Domain Driven Design - Prof. Rodrigo Vieira [email protected]


Em alguns casos, isso não é um problema. Mas em outros, isso pode ser bem grave.

Isso é importante! Nem sempre a duplicação de elementos é algo ruim. As vezes é até
necessário.

Pense no cálculo de médias de todos os alunos de uma sala. É bem provável que
existam notas iguais. Logo, devemos manter todas elas.

Mas há casos onde a duplicação é um problema. Não existem 2 alunos com o mesmo
nome e com a mesma chamada na faculdade.

Podemos impedir que isso aconteça, por meio da utilização de outras coleções do Java,
como as que implementam a interface java.util.Set:

No diagrama acima, temos 2 classes que implementam essa interface. Outras classes
podem ser encontradas neste link.

A classe HashSet trabalha com alguns controles para impedir a repetição de objetos dentro
dela. Vamos então aplicá-la no nosso exemplo:

@Test
void testeDeUsoDeHashSet() {
Aluno claudiaDaSilva = new Aluno("Claudia da Silva", "550444",
"1TDSPY");
Aluno fernandoFerreira = new Aluno("Fernando Ferreira", "551088",
"1TDSPY");
Aluno joaoSantos = new Aluno("João Santos", "654032", "1TDSPY");

Set<Aluno> alunos = new HashSet<>();


alunos.add(fernandoFerreira);
alunos.add(claudiaDaSilva);
alunos.add(joaoSantos);
alunos.add(fernandoFerreira);

Domain Driven Design - Prof. Rodrigo Vieira [email protected]


assertEquals(3, alunos.size());
}

Veja que, embora tenhamos adicionado 4 alunos, temos apenas 3 na coleção, graças a
coleção utilizada.

Falta então entendermos como funciona a classe TreeSet.

Como ordenar elementos? A classe TreeSet


Dado que temos uma coleção de alunos, podemos classificá-los de diversas maneiras:

● de acordo com suas notas


● de acordo com seu número de chamada
● de acordo com seu nome
● algum outro critério

No nosso caso, podemos classificá-los de acordo com seu nome. Assim podemos criar uma
lista de chamada com esses alunos por exemplo.

Para isso, vamos copiar o método acima e substituir o HashSet pela nossa nova coleção.
Como ambas implementam a interface Set, o ajuste será bem simples:

@Test
void testeDeUsoDeTreeSet() {
Aluno claudiaDaSilva = new Aluno("Claudia da Silva", "550444",
"1TDSPY");
Aluno fernandoFerreira = new Aluno("Fernando Ferreira", "551088",
"1TDSPY");
Aluno joaoSantos = new Aluno("João Santos", "654032", "1TDSPY");

Set<Aluno> alunos = new TreeSet<>();


alunos.add(fernandoFerreira);
alunos.add(claudiaDaSilva);
alunos.add(joaoSantos);
alunos.add(fernandoFerreira);

assertEquals(3, alunos.size());
}

Mas ao rodarmos o teste acima:

Domain Driven Design - Prof. Rodrigo Vieira [email protected]


O que seria essa tal de Comparable?

A interface java.lang.Comparable
Conforme dito acima, é possível compararmos alunos de diversas formas, e escolhemos a
ordenação por nome, para criarmos a lista de presença dos alunos.

Demonstramos interesse, mas em nenhum momento escrevemos código para isso.

Para resolver isso, precisaremos realizar as seguintes alterações:

● implementar a interface Comparable na classe Aluno:

public class Aluno implements Comparable<Aluno> {

● adicionar o método que a interface traz ao aluno:

@Override
public int compareTo(Aluno outro) {
return nome.compareTo(outro.nome);
}

A interface Comparable é implementada em diversas classes da biblioteca padrão de


Java. Entre elas a classe String. Por isso temos o método compareTo() também na
classe String.

Ele trabalha da seguinte maneira:

Domain Driven Design - Prof. Rodrigo Vieira [email protected]


● retorna um valor negativo se o objeto que o contém contém um valor "antes" do
objeto passado como parâmetro
● retorna 0 se os valores do objeto que o contém e o objeto passado como parâmetro
forem iguais
● retorna um valor positivo se o objeto que o contém contém um valor "após" o valor
do objeto passado com parâmetro.

Com ele implementado, os testes voltaram a passar:

Podemos também verificar se houve uma ordenação de fato dos alunos. Para isso,
podemos adicionar o código abaixo no nosso teste:

for(Aluno aluno : alunos) {


System.out.println(aluno.getNome());
}

A saída no console será semelhante a abaixo:

Claudia da Silva
Fernando Ferreira
João Santos

Exercícios
38.1 - Faça os mesmos testes que fizemos com os alunos, mas agora com os livros. Tente
trabalhar com Lists e Sets. Pode ser que seja necessário escrever mais algum código na
classe Livro. Sem problemas!

Domain Driven Design - Prof. Rodrigo Vieira [email protected]

Você também pode gostar