List<E>
Até agora, sempre que precisámos de representar coleções de objetos usámos arrays
. Existem outros tipos não primitivos, definidos através de classes e interfaces na biblioteca do Java, que nos permitem representar coleções de objetos. Estas classes e interfaces compõem aquilo que usualmente se chama de collection framework.
Para já, vamos ver só o interface List
e uma das suas várias implementações – a classe ArrayList
, ambos do pacote java.util.
Quando pensamos no conceito de lista, imaginamos uma coleção ordenada, uma sequência de elementos. Sobre essa coleção podemos adicionar elementos, retirar elementos, aceder a um elemento numa dada posição da lista, etc.
Se tivermos três listas – uma com elementos do tipo Jogo
, outra com elementos do tipo Integer
e ainda outra com elementos do tipo Pessoa
–, percebemos que as operações atrás referidas não diferem pelo facto de os tipos dos elementos de cada lista serem diferentes, ou seja, o mecanismo das operações não depende do tipo específico dos elementos que a lista contém.
Então, ter três classes distintas que definem listas de elementos do tipo Jogo
, do tipo Integer
e do tipo Pessoa
, respetivamente, seria um desperdício de tempo e espaço, pois elas seriam todas iguais excetuando no tipo de retorno ou de parâmetro de um ou outro método (como, por exemplo, do método que acede ao elemento numa dada posição da lista e do método que insere um elemento na lista).
Em vez disso, define-se o tipo genérico List<E>
que abstrai o tipo dos elementos da lista:
Em Java, o interface
List<E>
define
- o tipo de dados lista de elementos de um tipo
E
qualquer, ou seja,- as operações que qualquer classe que implemente uma coleção ordenada de elementos deverá suportar, qualquer que seja o tipo dos seus elementos.
Alguns dos métodos definidos no interface List<E>
(https://docs.oracle.com/javase/9/docs/api/java/util/List.html):
void add(int index, E element)
que insere o objeto element
na posição de índice index
da listaboolean add(E element)
que adiciona o elemento element
no fim da listaboolean contains(Object o)
que retorna true
se a lista contém o elemento o
E get(int index)
que retorna o elemento que está na posição de índice index
na listaint indexOf(Object o)
que retorna o índice da 1ª ocorrência do elemento o
na lista, ou -1 se não existeboolean isEmpty()
que retorna true
se a lista não tem elementosE remove(int index)
que remove o elemento na posição de índice index
boolean remove(Object o)
que remove a primeira ocorrência do elemento o
na lista, se presenteE set(int index, E element)
que substitui o elemento na posição de índice index
por element
int size()
que retorna o número de elementos na listaO primeiro elemento de uma lista myList
é o que está na posição de índice zero. O último elemento está na posição de índice myList.size()-1
Uma das classes que implementam o interface List<E>
é a classe ArrayList<E>
(https://docs.oracle.com/javase/9/docs/api/java/util/ArrayList.html).
Um tipo genérico pode ter mais que uma variável de tipo. Um exemplo é o interface Map<K,V>
do pacote java.util.
Para podermos usar uma lista num programa Java teremos que instanciar a variável de tipo E
. Somente tipos não primitivos podem ser usados para instanciar as variáveis de tipo de um tipo genérico.
Por exemplo, se eu quiser usar uma lista de inteiros no meu programa, terei que instanciar a variável de tipo com Integer
, que é uma classe wrapper (embrulho) dos inteiros.
Um parentesis:
Cada tipo primitivo tem uma classe correspondente (chamada wrapper ) e as conversões entre ambas são feitas de forma automática:
- Num programa com as seguintes declarações de variáveis:
Integer wrap;
int i;
- as seguintes instruções têm o mesmo efeito:
xxxxxxxxxx
wrap = 17;
wrap = Integer.valueOf(17);
- e as seguintes também:
xxxxxxxxxx
i = wrap;
i = wrap.intValue();
Voltando agora à utilização de tipos genéricos. O seguinte programa declara, cria e usa uma lista de inteiros:
ximport java.util.ArrayList;
import java.util.Random;
public class ExemploClienteDeList {
public static void main(String[] args) {
ArrayList<Integer> listaInts = new ArrayList<Integer>();
Random gerador = new Random();
int valor = gerador.nextInt(10);
while(valor != 9) {
listaInts.add(valor);
valor = gerador.nextInt(10);
}
for (Integer val : listaInts) {
System.out.print(val + " ");
}
System.out.println();
int indice = listaInts.indexOf(2);
if(indice != -1) {
System.out.println("O valor 2 foi o " + (indice + 1) +
"º valor a ser gerado");
} else {
System.out.println("O valor 2 nao foi gerado");
}
}
}
Um possível output deste programa:
xxxxxxxxxx
7 6 0 2 3 8 6 6 2 1 2 6 4 8 1 2 0 3
O valor 2 foi o 4º valor a ser gerado
Agora que já conhece os tipos List
e ArrayList
, antes de passarmos para o próximo capítulo aproveitamos para modificar o tipo de retorno do método vencedores
do interface Ganhavel
para retornar uma List<String>
em vez de um array de String
. Irá notar que a nova classe Jogo
no próximo capítulo irá beneficiar do uso mais intensivo destes dois tipos de dados.
x/**
* Este interface define um tipo de dados representando uma atividade que tem
* participantes com diferentes pontuacoes. Uma vez a atividade terminada,
* podem ser conhecido(s) o(s) vencedor(es)
*/
public interface Ganhavel {
/**
* A designacao deste ganhavel.
*/
String designacao();
/**
* Os nomes dos vencedor(es) deste ganhavel
* @return Os nomes dos participantes deste ganhavel que venceram
* @requires this.terminou()
*/
List<String> vencedores();
/**
* Este ganhavel jah terminou?
*/
boolean terminou ();
/**
* Existe um participante com um dado nome neste ganhavel?
* @param nome O nome do participante.
* @return true se existe um participante com este nome neste ganhavel
* false cc
*/
boolean estahEmJogo (String nome);
/**
* A pontuacao de um dado participante deste ganhavel
* @param nome O nome do participante.
* @requires this.estahEmJogo(nome)
* @return A pontuacao do participante com este nome
*/
int pontuacao (String nome);
}
Anterior: 13.4. O interface Ganhavel
Seguinte: 14. Herança