java.util.Arrays

Propaganda
Programação por Objectos
Java
Parte 9: Classes utilitárias
LEEC@IST
Java – 1/83
Introdução (1)
• O Java disponibiliza um conjunto de classes utilitárias:
– com funcionalidades importantes para o
programador.
– distribuídas no ambiente de desenvolvimento em
pacotes (dentro do arquivo src.zip)
•
src/java/lang
»
LEEC@IST
# classes de linguagem (Integer,…)
importado automaticamente
•
•
src/java/util
src/java/math
# utilitários diversos (Vector,…)
# classe Math
•
src/java/io
# classes entrada/saída
Java – 2/83
Introdução (2)
• O J2SE disponibiliza diversos grupos de interfaces.
Neste capítulo abordamos 4:
1. Comparator e Comparable – descrevem comparações
entre objectos (por exemplo, para ordenação).
2. Collection – descrevem colecções de objectos.
3. Map – descrevem funções entre objectos.
4. Iterator – descrevem varrimentos sobre colecções de
objectos, sem conhecer a forma como estão organizados.
• O código das classes pode ser consultado em
http://www.docjar.com
LEEC@IST
Java – 3/83
Introdução (3)
Hierarquia geral das interfaces de ADTs no J2SE 5
<<interface>> E
Iterable
<<interface>>
Collection
E
<<interface>> E <<interface>> E <<interface>> E
Set
List
Queue
<<interface>> E
SortedSet
LEEC@IST
Java – 4/83
Introdução (4)
Hierarquia geral das interfaces de ADTs no J2SE 5
<<interface>> E
Iterator
<<interface>> E
ListIterator
LEEC@IST
<<interface>> K,V
Map
<<interface>> K,V
SortedMap
<<interface>> K,V
ConcurentMap
Java – 5/83
Ordenação (1)
• Classes que envolvem ordenação implementam uma
de duas interfaces:
– Comparable
– Comparator
LEEC@IST
Java – 6/83
Interface Comparable (1)
• Usada quando existe uma ordem natural (ex:
Character, Integer, Date).
• Implementada dentro da classe pelo método
CompareTo, que implica ordem total dentro da classe.
• Mais simples de implementar, mas menos flexível
(que a interface Comparator).
LEEC@IST
Java – 7/83
Interface Comparable (2)
public interface Comparable<T> {
public int compareTo(T other);
}
•
Valor retornado pelo compareTo deve ser:
< 0 se o objecto sobre o qual o método é chamado é menor
que objecto recebido como parâmetro
= 0 se o objecto sobre o qual o método é chamado e o
objecto recebido como parâmetro são iguais por
equivalência (equals)
> 0 caso contrário
LEEC@IST
Java – 8/83
Interface Comparable (3)
public class Conta implements Comparable<Conta> {
private static long numProxConta = 0;
protected long numConta; // número da conta
protected float quantia; // saldo actual
//...
public boolean equals(Object obj) {
return numConta==((Conta)obj).numConta;
}
public int compareTo(Conta other) {
if (numConta > other.numConta) return 1;
else if (numConta == other.numConta) return 0;
else return -1;
}
//...
}
LEEC@IST
Java – 9/83
Interface Comparable (4)
Conta mc = new Conta(“Manuel Silva”,1000);
Conta outra = new Conta(“Luís Silva”,200);
System.out.println(mc.compareTo(mc));
System.out.println(mc.compareTo(outra));
System.out.println(outra.compareTo(mc));
No terminal é impresso
LEEC@IST
0
1
-1
Java – 10/83
Interface Comparable (5)
•
As interfaces são tipos, por isso podemos ter:
Comparable<Conta> cc;
•
É possível definir, por exemplo, um algoritmo de ordenação
para ordenar uma tabela de objectos Comparable (sem olhar a
que classe é que esses objectos pertencem):
class Ordena {
static Comparable<?>[] ordena(Comparable<?>[] objs) {
// detalhes da ordenação ...
return objs;
}
}
LEEC@IST
Java – 11/83
Interface Comparable (6)
• A classe java.util.Arrays oferece um método
que permite ordenar objectos numa tabela de
Object segundo a sua ordenação natural:
public static void sort(Object[] a,
int fromIndex, int toIndex)
– Ordena os objectos da tabela a do índice fromIndex
(inclusivé) ao índice toIndex (exclusivé).
– Todos os elementos da tabela no intervalo [fromIndex,
toIndex] têm de implementar a interface Comparable.
– Todos os elementos nesse intervalo têm de ser
mutuamente comparáveis (i.e., obj1.compareTo(obj2)
não deve lançar uma excepção ClassCastException).
LEEC@IST
Java – 12/83
Interface Comparable (7)
public class Ordena {
static Comparable<?>[] ordena(Comparable<?>[] objs) {
Comparable<?>[] res = new Comparable<?>[objs.length];
System.arraycopy(objs, 0, res, 0, objs.length);
java.util.Arrays.sort(res, 0, res.length);
return res;
}
}
Conta mc = new Conta(“Manuel Silva”,1000);
Conta outra = new Conta(“Luís Silva”,200);
Comparable<?>[] contas = new Comparable<?>[2];
contas[0]=outra;
contas[1]=mc;
contas = Ordena.ordena(contas);
LEEC@IST
Java – 13/83
Interface Comparator (1)
• Usada quando existe uma ordem dependente da
aplicação (ex: ordenação de uma lista de alunos
pode ser feita por nome, por número ou pela
classificação).
• Implementada fora da classe (mas pode usar
compareTo sobre os atributos da classe),
concretizando a interface Comparator.
• Implementação mais complexa, mas mais potente
(que a interface Comparable).
LEEC@IST
Java – 14/83
Interface Comparator (2)
public interface Comparator<T> {
public int compare(T o1, T o2);
}
•
Valor retornado pelo compare deve ser:
< 0 se o objecto o1 é menor que objecto o2
= 0 se o objecto o1 é igual ao objecto o2
> 0 caso contrário
LEEC@IST
Java – 15/83
Interface Comparator (3)
• Características do método compare:
– sgn(compare(x,y)) == -sgn(compare(y,x))
para todo x, y.
– Transitividade:
((compare(x,y)>0) && (compare(y,z)>0))
implica compare(x,z)>0.
– compare(x,y)==0
implica sgn(compare(x,z)) == sgn(compare(y,z))
para todo z.
– Inconsistência com equals: não é necessário que
(compare(x,y)==0) == (x.equals(y)).
LEEC@IST
Java – 16/83
Interface Comparator (3)
• Apesar de não fazer sentido definir uma ordenação
natural de contas por saldo, pode ser necessário
algures numa aplicação ordenar contas por saldo...
import java.util.Comparator;
public class ComparadorContaPorSaldo implements Comparator<Conta> {
public int compare(Conta o1, Conta o2) {
if (o1.quantia > o2.quantia) return 1;
else if (o1.quantia == o2.quantia) return 0;
else return -1;
}
}
LEEC@IST
Java – 17/83
Interface Comparator (4)
• A classe java.util.Arrays oferece um método
genérico que permite ordenar objectos numa tabela
segundo a ordem induzida por um Comparator:
public static <T> void sort(
T[] a, int fromIndex, int toIndex,
Comparator<? super T> c)
– Ordena os objectos da tabela a do índice fromIndex
(inclusivé) ao índice toIndex (exclusivé).
– Todos os elementos nesse intervalo têm de ser mutuamente
comparáveis pelo Comparator (i.e.,
obj1.compare(obj2) não deve lançar uma excepção
ClassCastException).
LEEC@IST
Java – 18/83
Interface Comparator (5)
• Uma tabela de contas poderia então ser ordenada por
saldo da seguinte forma:
Conta[] contas = new Conta[2];
Contas[0] = new Conta(“Manuel Silva”,1000);
Contas[1] = new Conta(“Luís Silva”,200);
java.util.Arrays.sort(
contas, 0, contas.length,
new ComparadorContaPorSaldo());
LEEC@IST
Java – 19/83
Interface Comparator (6)
• Dada uma lista de estudantes, o critério natural de
ordenação seria por número de estudante. Para ordenar
uma tal lista por nome:
import java.util.Comparator;
public class ComparadorEstudantePorNome
implements Comparator<Estudante> {
public int compare(Estudante o1, Estudante o2) {
String nome1 = o1.primeiroNome();
String nome2 = o2.primeiroNome();
if (nome1.equals(nome2)) {
nome1 = o1.últimoNome();
nome2 = o2.últimoNome();
return nome1.compareTo(nome2);
} else return nome1.compareTo(nome2);
}
}
LEEC@IST
Java – 20/83
Interface Comparator (7)
public static void main(String[] args) {
Estudante[] estudantes = new Estudante[args.length];
for(int i=args.length-1; i>=0; i--)
estudantes[i] = new Estudante(args[i]);
imprimirEstudantes(estudantes);
System.out.println("*** Ordenado por nome ***");
java.util.Arrays.sort(estudantes,
new ComparadorEstudantePorNome());
imprimirEstudantes(estudantes);
}
LEEC@IST
Java – 21/83
Interface Comparator (8)
• Se se pretender ordenar a tabela de estudantes por
outro critério, por exemplo, por nota, basta
desenvolver outra implementação de Comparable e
chamar o método java.util.Arrays.sort.
System.out.println("*** Ordenado por nota ***");
java.util.Arrays.sort(estudantes,
new ComparadorEstudantePorNota());
LEEC@IST
Java – 22/83
Interface Iterator
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
• A interface Iterator deve ser implementada por
classes que pretendam iterar sobre os seus
elementos, um por um.
LEEC@IST
Java – 23/83
Interface Iterable
public interface Iterable<E> {
Iterator<E> iterator();
}
• Uma classe que implemente a interface Iterable
oferece um Iterator que depois pode ser usado
no ciclo for-each.
LEEC@IST
Java – 24/83
Interface Collection (1)
• Uma colecção, ou contentor, é um objecto que
agrupa diversos objectos (eventualmente repetidos)
numa unidade.
• Protótipos de métodos agrupados por três tipos:
– Operações básicas.
– Operações de manipulação a todos os elementos
de uma só vez (bulk).
– Operações que convertem elementos numa
tabela.
LEEC@IST
Java – 25/83
Interface Collection (2)
public interface Collection<E> extends Iterable<E> {
// Basic operations
int
size();
boolean
isEmpty();
boolean
contains(Object elem);
boolean
add(E elem);
boolean
remove(Object elem);
Iterator<E> iterator();
// Bulk operations
boolean
containsAll(Collection<?> coll);
boolean
addAll(Collection<? extends E> coll);
boolean
removeAll(Collection<?> coll);
boolean
retainAll(Collection<?> coll);
void
clear();
// Array operations
Object[]
toArray();
<T> T[]
toArray(T dest[]);
}
LEEC@IST
Java – 26/83
Interface Collection (3)
• Todos os métodos que necessitam de verificar
igualdade entre objectos utilizam a igualdade por
equivalência, baseada no equals (contains,
add, remove, containsAll, addAll,
removeAll e retainAll).
• A interface Collection não faz qualquer restrição a
que elementos null sejam adicionados à colecção.
LEEC@IST
Java – 27/83
Interface Collection (4)
•
Pode usar-se um ciclo for e os métodos da interface Iterator
para varrer os objectos de uma colecção:
–
–
–
É possível adicionar e remover (add e remove) objectos à
colecção durante o varrimento.
É possível alterar os objectos da colecção durante o varrimento.
É possível iterar sobre múltiplas colecções.
public class RemoverStringsCurtas {
public static void remover(Collection<String> c){
// elimina strings unitárias ou nulas
for (Iterator<String> i=c.iterator(); i.hasNext(); )
if (i.next().length()<2)
i.remove();
}
}
LEEC@IST
Java – 28/83
Interface Collection (5)
•
O varrimento pode ser facilitado com a instrução for-each:
–
–
–
–
A vantagem do for-each é puramente sintática.
Não é possível adicionar e remover (add e remove) objectos à
colecção durante o varrimento.
É possível alterar os objectos da colecção durante o varrimento.
Não é possível iterar sobre múltiplas colecções.
public class ImprimirStringsCurtas {
public static void imprimir(Collection<String> c){
for(String s:c)
if (s.length()<2)
System.out.println(s);
}
}
LEEC@IST
Java – 29/83
Interface Collection (6)
• Da interface Collection são derivadas outras
interfaces:
– Set : colecção sem duplicações
– List : lista de elementos
– Queue : fila de elementos
LEEC@IST
Java – 30/83
Interface Collection (7)
<<interface>> E
Iterable
<<interface>>
Collection
E
<<abstract>> E
AbstractSet
<<interface>> E
Set
LEEC@IST
E
<<abstract>>
AbstractCollection
<<abstract>> E
AbstractList
<<interface>> E
List
<<abstract>> E
AbstractQueue
<<interface>> E
Queue
Java – 31/83
Implementação de interfaces (1)
• Existem diversas estruturas subjacentes de dados
para implementar interfaces:
1. Lineares: os objectos são ordenados por
posições, cada objecto tem apenas um
predecessor (excepto primeiro) e um sucessor
(excepto último).
2. Hierárquicas: cada objecto tem um único
predecessor (excepto a raíz) e pode ter um
número fixo de sucessores.
3. Desordenadas: não existe uma relação entre
dois objectos.
LEEC@IST
Java – 32/83
Implementação de interfaces (2)
• O J2SE 5 implementa as interfaces Set/List/Map
por intermédio de quatro estruturas de dados:
– Tabelas de dispersão (hash tables).
– Vectores de dimensão variável.
– Árvores balanceadas.
– Listas ligadas.
Estrutura de dados subjacente
Interfaces
Hash
Vector dim. var.
Set
List
Map
HashSet
--HashMap
--ArrayList
---
LEEC@IST
Árv. bal.
Lista Ligada
TreeSet
----LinkedList
TreeMap
---
Hash + Lista Ligada
LinkedHashSet
--LinkedHashMap
Java – 33/83
Tabelas de dispersão
(hash tables)
•
•
•
•
•
•
Fazem o mapeamento de uma chave num valor.
As chaves são utilizadas para calcular inteiros (hash) que
devem ser diferentes para cada chave e estar uniformemente
distribuídos (dispersos) pelo conjunto dos inteiros.
Os pares chave valor são armazenados num conjunto de
“baldes”. O balde correspondente a cada par chave tabela é
determinado directamente do hash (por exemplo utilizando os
bits menos significativos).
O número de baldes é fixo no na construção da tabela. Cada
balde pode conter zero ou N chaves. A tabela deve ser
dimensionada para cada balde conter tipicamente zero ou um
elemento, resultando em acessos muito rápidos.
Bons para insert search e delete, mas maus para funções de
select e sort.
Versões mais lista evitam ordem de iteração aleatória.
LEEC@IST
Java – 34/83
Arvores balanceadas
F
•
•
•
Implementação de uma árvore
Red-Black.
Relacionadas com arvores 2-34 que garantem que a arvore se
encontra exactamente
balanceada em cada instante
sem um aumento muito
significativo do peso
computacional.
Exemplo de uma rotação à
esquerda em F para balancear
uma árvore.
D
G
B
E
A
D
B
A
LEEC@IST
C
F
C
E
G
Java – 35/83
Vectores de dimensão variável
• São re-alocados e copiados quando a sua
capacidade excede determinado limite.
LEEC@IST
Java – 36/83
Interface Set (1)
<<abstract>> E
AbstractSet
E
TreeSet
E
HashSet
E
<<interface>> E
Set
LinkedHashSet
<<interface>> E
SortedSet
LEEC@IST
Java – 37/83
Interface Set (2)
• A interface Set não acrescenta nenhum método:
– Apenas define os mesmos métodos de
Collection.
– São impostas restrições extra aos métodos add
e equals, por forma a não haver elementos
duplicados.
LEEC@IST
Java – 38/83
Interface Set (3)
• Algumas concretizações da interface Set:
– HashSet: melhor, para a maioria das utilizações.
– LinkedHashSet: impõe ordem no Iterator (ordem de
inserção).
– TreeSet: impõe ordem no Iterator (ordem natural ou
ordem especificada por um objecto Comparator).
• É de evitar expor a implementação:
Set s = new HashSet(); // preferível
HashSet s = new HashSet(); // a evitar!
LEEC@IST
Java – 39/83
Interface Set (4)
• Operações típicas sobre conjuntos:
– União:
s1.addAll(s2); // s1 passa a união de s1 e s2
– Intersecção:
s1.retainAll(s2); // s1 passa a intersecção de s1 e s2
– Diferença:
s1.removeAll(s2); // s1 passa a diferença de s1 e s2
– Subconjunto:
s1.containsAll(s2); // testa se s2 é subconjunto de s1
LEEC@IST
Java – 40/83
Interface Set (5)
• Truque para remover elementos duplicados de uma
colecção:
Collection comDuplicados;
//...
Collection semDuplicados = new HashSet();
semDuplicados.addAll(comDuplicados);
Collection semDuplicados = new HashSet(comDuplicados);
LEEC@IST
Java – 41/83
Interface Set (6)
Set<String> s1 = new HashSet<String>();
s1.add("Ana"); s1.add("Joao");
System.out.print("s1 = "); imprimir(s1);
Set<String> s2 = new HashSet<String>();
s2.add("Joao"); s2.add("Luis");
System.out.print("s2 = "); imprimir(s2);
Set<String> s3;
s3 = new HashSet<String>(s1); s3.addAll(s2);
System.out.print("União(s1,s2) = "); imprimir(s3);
s3 = new HashSet<String>(s1); s3.retainAll(s2);
System.out.print("Intersecção(s1,s2) = "); imprimir(s3);
s3 = new HashSet<String>(s1); s3.removeAll(s2);
System.out.print("Diferença(s1,s2) = "); imprimir(s3);
LEEC@IST
Java – 42/83
Interface Set (7)
Relativamente ao exemplo anterior:
• O método estático imprimir imprime os elementos
de um conjunto, por exemplo, com um iterador:
static void imprimir(Collection<String> s) {...}
• No terminal é impresso:
s1 = Joao Ana
s2 = Joao Luis
União(s1,s2) = Joao Luis Ana
Intersecção(s1,s2) = Joao
Diferença(s1,s2) = Ana
LEEC@IST
Java – 43/83
Interface List (1)
<<abstract>> E
AbstractList
E
ArrayList
E
Vector
E
<<abstract>>
AbstractSequentialList
E
<<interface>> E
List
Stack
E
LinkedList
<<interface>> E
Queue
LEEC@IST
Java – 44/83
Interface List (2)
public interface List<E> extends Collection<E> {
E get(int index);
E set(int index, E elem);
void add(int index, E elem);
E remove(int index);
int indexOf(Object elem);
int lastIndexOf(Object elem);
List<E> subList(int min, int max);
ListIterator<E> listIterator(int index);
ListIterator<E> listIterator();
}
LEEC@IST
Java – 45/83
Classe ArrayList (1)
• É uma implementação de List que guarda os seus
objectos numa tabela:
– A tabela tem uma capacidade inicial.
– Quando a capacidade inicial da tabela deixa de ser suficiente
é afectada uma nova tabela e o seu conteúdo é copiado.
– Um valor correcto para a capacidade inicial da ArrayList
melhora o seu desempenho.
• Complexidade:
– Adicionar (na posição i) e remover (da posição i): O(n-i)
onde n é o tamanho da lista e i<n.
• Adicionar (no fim) e remover (do fim): O(1)
– Aceder a um elemento (em qualquer posição): O(1)
LEEC@IST
Java – 46/83
Classe ArrayList (2)
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, ...
{
ArrayList() {...}
ArrayList(int initialCapacity) {...}
ArrayList(Collection<? extends E> coll) {...}
void trimToSize() {...}
void ensureCapacity(int minCapacity) {...}
}
• Em caso de omissão, a capacidade inicial de um
ArrayList é 10.
LEEC@IST
Java – 47/83
Classe LinkedList (1)
• É uma implementação de List como uma lista
duplamente ligada.
• A classe LinkedList implementa ainda a interface
Queue.
• Complexidade:
– Adicionar (na posição i) e remover (da posição i):
O(min{i,n-i}), onde n é o tamanho da lista.
•
Adicionar (no princípio ou fim) e remover (do princípio ou
fim): O(1).
– Aceder a um elemento na posição i: O(min{i,n-i}), onde n
é o tamanho da lista.
LEEC@IST
Java – 48/83
Classe LinkedList (2)
• Da análise da complexidade podemos concluir
que:
– Deve ser usada uma LinkedList sempre que:
• Se tem uma lista cuja dimensão varia muito.
• É importante adicionar ou remover elementos numa
posição arbitrária da lista.
– É preferível usar uma ArrayList sempre que:
• Se quer uma lista cujos elementos são sempre
adicionais no fim.
• Se quer aceder aos seus elementos de uma forma
muito eficiente.
LEEC@IST
Java – 49/83
Classe LinkedList (3)
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Queue<E>, ...
{
LinkedList() {...}
LinkedList(Collection<? Extends E> coll) {...}
E getFirst() {...}
E getLast {...}
E removeFirst() {...}
E removeLast() {...}
void addFirst(E elem) {...}
void addLast(E elem) {...}
}
LEEC@IST
Java – 50/83
Classes de legado
• As interfaces/classes relacionadas com colecções
apresentadas até aqui são novas no pacote
java.util.
• O java.util sempre conteve outras colecções,
que mantém por razões de compatibilidade de
versões. Destacam-se:
– Vector
– Stack
• Apesar de Vector e Stack serem classes de
legado, implementam a interface List, logo
funcionam como qualquer colecção.
LEEC@IST
Java – 51/83
Classe Vector (1)
public class Vector<E>
extends AbstractList<E>
implements List<E>, ...
{
//Métodod novos, tal como em ArrayList
Vector() {...}//ArrayList()
Vector(int initialCapacity) {...}//ArrayList(initialCapacity)
Vector(Collection<? Extends E> coll) {...}//ArrayList(coll)
void trimToSize() {...}
void ensureCapacity(int minCapacity) {...}
//... Diferença para ArrayList (próximo slide)
• Em caso de omissão, a capacidade inicial de um Vector
é 10.
LEEC@IST
Java – 52/83
Classe Vector (2)
//Diferença para ArrayList
Vector(int initialCapacity, int capacityIncrement) {...}
void copyInto(Object[] anArray) {...}
int indexOf(Object elem, int index) {...}
int lastIndexOf(Object elem, int index) {...}
void setSize(int newSize) {...}
int capacity() {...}
//Métodos de legado com equivalência em ArrayList
void addElement(E elem) {...}//add(elem)
void insertElement(E elem, int index) {...}//add(index,elem)
void setElement(E elem, int index) {...}//set(index,elem)
void removeElement(int index) {...}//remove(index)
boolean removeElement(Object elem) {...}//remove(elem)
void removeAllElements() {...}//clear()
E elementAt(int index) {...}//get(index)
E firstElement() {...} //get(0)
E lastElement() {...} //get(size()-1)
}
LEEC@IST
Java – 53/83
Classe Vector (3)
• Utilização de Vector como classe de legado:
Vector vector = new Vector(20);
• Utilização de Vector como colecção genérica:
Vector<?> vector = new Vector<String>(20);
Vector<String> vector = new Vector<String>(20);
LEEC@IST
Java – 54/83
Classe Vector (4)
import java.util.Vector;
public class Main {
private final int SIZE = 10;
private Vector vector = new Vector(SIZE);
//...
public static void main(String[] args) {
Integer iobj;
for(int index=0;index<SIZE;index++)
vector.addElement(new Integer(index));
for(int index=2;index<SIZE;index+=2){
iobj=(Integer)vector.elementAt(index-1);
vector.setElementAt(new Integer(2*iobj.intValue()),index);
}
for(int index=0;index<SIZE;index++)
System.out.println(
“Índice = “+index+“ “+vec.elementAt(index));
}
}
LEEC@IST
Java – 55/83
Classe Vector (5)
import java.util.Vector;
public class Main {
private final int SIZE = 10;
private Vector<Integer> vector = new Vector<Integer>(SIZE);
//...
public static void main(String[] args) {
Integer iobj;
for(int index=0;index<SIZE;index++)
vector.add(new Integer(index));
for(int index=2;index<SIZE;index+=2){
iobj=(Integer)vector.get(index-1);
vector.set(new Integer(2*iobj.intValue()),index);
}
for(int index=0;index<SIZE;index++)
System.out.println(
“Índice = “+index+“ “+vec.get(index));
}
}
LEEC@IST
Java – 56/83
Classe Vector (6)
• A implementação genérica de Vector
permite que chamar directamente os métodos
da classe tipo.
• Exemplo:
– Considere ContaOrdem e ContaPrazo
descendente da classe abstracta Conta.
– Na Conta é definido o método abstracto juro(),
que é implementado nas classes concretas.
LEEC@IST
Java – 57/83
Classe Vector (7)
Vector<Conta> arquivo = new Vector<Conta>();
//...
arquivo.add(new ContaOrdem());
arquivo.add(new ContaPrazo());
//...
for(i=0;i<arquivo.size();i++)
(arquivo.get(i)).juro();
• O método juro() executa a implementação da classe
concreta correspondente (ligação dinâmica).
• A criação de novas classes (de um subtipo de Conta)
não requerem a alteração do código existente,
facilitando a evolução das aplicações informáticas.
LEEC@IST
Java – 58/83
Classe Stack
• A classe Stack é uma classe derivada de Vector
que adiciona métodos para obter uma estrutura de
dados FIFO.
public class Stack<E> extends Vector<E> {
Stack();
E push(E item);
E pop();
E peek();
boolean empty();
int search(Object o);
}
LEEC@IST
Java – 59/83
Implementações de List
Vantagens
– Resolvem o inconveniente da dimensão das
tabelas não poderem ser alteradas após a
instanciação.
Inconvenientes
– Apenas podem armezenar objectos (dados de
tipo primitivo têm de ser armazenados como
objectos de embrulho).
– Acesso às tabelas é mais eficiente.
LEEC@IST
Java – 60/83
Classe Arrays (1)
• A classe estática Arrays é criada pelo J2SE e
disponibiliza métodos para manipulação de tabelas.
• A grande maioria dos métodos têm várias
sobreposições:
– Uma para tabelas de cada tipo primitivo.
– Uma para tabelas de Object.
• Os métodos são ainda disponibilizados em duas
variantes:
– Uma actuando em toda a tabela.
– Outra actuando numa subtabela especificada por dois
índices.
LEEC@IST
Java – 61/83
Classe Arrays (2)
• Os métodos da classe Arrays são:
– static void sort: Ordenação ascendente, com parâmetros:
1. Tabela a ordenar (obrigatório)
2. Dois índices, mínimo e máximo, que definem a subtabela (por
omissão, é toda a tabela)
3. Um objecto Comparator, que induz ordem nos elementos da
tabela (por omissão, ordem natural definida pelo Comparable)
– static int binarySearch: Procura binária (a tabela tem de
estar ordenada em ordem ascendente), com parâmetros:
1. Tabela a procurar (obrigatório)
2. Valor a pesquisar (obrigatório)
3. Um objecto Comparator, que induz ordem nos elementos da
tabela (por omissão, ordem natural definida pelo Comparable).
LEEC@IST
Java – 62/83
Classe Arrays (3)
Integer inteiros[] = new Integer[2];
inteiros[0]=1;
inteiros[1]=2;
System.out.println(Arrays.binarySearch(inteiros,1));
inteiros[0]=2;
inteiros[1]=1;
System.out.println(Arrays.binarySearch(inteiros,1));
No terminal é impresso
LEEC@IST
0
-1
Java – 63/83
Classe Arrays (4)
– static void fill: Preenchimento de posições, com
parâmetros:
1. Tabela a preencher (obrigatório)
2. Dois índices, mínimo e máximo, que definem a subtabela (por
omissão, é toda a tabela)
3. Valor a inserir (obrigatório)
– static boolean equals: Verifica igualdade por equivalência
de duas tabelas, com parâmetros:
1. Duas tabelas do mesmo tipo (obrigatório)
– static boolean deepEquals: Verifica igualdade por
equivalência de tabelas aninhadas de qualquer dimensão, com
parâmetros:
1. Duas tabelas de tipo Object (obrigatório)
LEEC@IST
Java – 64/83
Classe Arrays (5)
– static int hashCode: devolve o código de dispersão da
tabela recebida como parâmetro (baseada no seu conteúdo).
– static int deepHashCode: devolve o código de
dispersão da tabela de tipo Object recebida como parâmetro
(baseada no seu conteúdo, e tendo em consideração
aninhamento).
– static String toString: devolve uma string que
representa o conteúdo da tabela recebida como parâmetro.
– static String deepToString: devolve uma string que
representa o conteúdo, tendo em consideração aninhamento,
da tabela de tipo Object recebida como parâmetro.
– static <T> List<T> asList(T… t): devolve uma List
com os elementos recebido como parâmetro.
• Este método actua como uma ponte entre tabelas e colecções
(para complementar o método toArray das colecções).
LEEC@IST
Java – 65/83
Classe Arrays (6)
Integer inteiros[][] = new Integer[2][5];
Arrays.fill(inteiros[0],0); Arrays.fill(inteiros[1],1);
System.out.println("inteiros="+Arrays.deepToString(inteiros));
Integer outro[][] = new Integer[2][5];
Arrays.fill(outro[0],0); Arrays.fill(outro[1],1);
System.out.println("outro="+Arrays.deepToString(outro));
System.out.println(inteiros.hashCode()+"\t"+
Arrays.hashCode(inteiros)+"\t"+
Arrays.hashCode(inteiros[0])+"\t"+Arrays.hashCode(inteiros[1])+"\t"+
Arrays.deepHashCode(inteiros));
System.out.println(outro.hashCode()+"\t"+
Arrays.hashCode(outro)+"\t"+
Arrays.hashCode(outro[0])+"\t"+Arrays.hashCode(outro[1])+"\t"+
Arrays.deepHashCode(outro));
No terminal é impresso
inteiros=[[0, 0, 0, 0, 0], [1, 1, 1, 1, 1]]
outro=[[0, 0, 0, 0, 0], [1, 1, 1, 1, 1]]
16795905 922240875
28629151 29583456 917088098
12115735 676418749
28629151 29583456 917088098
LEEC@IST
Java – 66/83
Classe Arrays (7)
List lista = new ArrayList();
lista.add(1);
lista.add("Hello");
Object[] objectos = new Object[2];
objectos = lista.toArray();
System.out.println(lista.equals(Arrays.asList(objectos)));
System.out.println(objectos.equals(lista.toArray()));
System.out.println(Arrays.equals(objectos,lista.toArray()));
No terminal é impresso true
false
true
LEEC@IST
Java – 67/83
Interface Queue (1)
<<interface>> E
Collection
<<interface>> E
Queue
E
<<abstract>>
AbstractCollection
<<abstract>>
AbstractQueue
E
E
PriorityQueue
LEEC@IST
Java – 68/83
Interface Queue (2)
public interface Queue<E> extends Collection<E> {
E element();
// mostra a cabeça
E peek();
// mostra a cabeça ou null
E remove();
// mostre e remove a cabeça
E pool();
// mostra e remove a cabeça ou null
boolean offer(E elem); // insere elemento
}
LEEC@IST
Java – 69/83
Interface Queue (3)
• Apesar de as colecções aceitarem elementos nulos,
uma Queue não deve ter elementos null, pois o
null é usado no retorno dos métodos peek e poll
para indicar que a Queue está vazia.
• A class LinkedList é a implementação mais
simples da interface Queue.
– Por razões históricas são permitidos elementos null
numa LinkedList.
– Deve evitar-se inserir elementos null numa LinkedList
sempre que esta for usada como uma Queue.
LEEC@IST
Java – 70/83
Classe PriorityQueue (1)
• A PriorityQueue é uma outra implementação de
Queue.
• A implementação da PriorityQueue é baseada
num acervo (heap).
• A cabeça da fila prioritária é o elemento menor que
a fila contém.
– O menor elemento é determinado pela ordem natural dos
elementos, ou indicado por um comparador entre dois
elementos.
– Se o menor elemento representa o elemento com menor
ou maior prioridade depende de como a ordem natural ou
o comparador fornecido estão definidos.
LEEC@IST
Java – 71/83
Classe PriorityQueue (2)
• O iterador da PriorityQueue não varre
necessariamente os elementos da fila por ordem de
prioridade. Na realidade, o iterator segue a ordem
de armazenamento no acervo.
• Apenas é garantido que remover elementos da fila
prioritária ocorre por ordem de prioridade.
LEEC@IST
Java – 72/83
Classe PriorityQueue (3)
• Construtores de PriorityQueue:
public PriorityQueue()
public PriorityQueue(int initialCapacity)
public PriorityQueue(int initialCapacity,
Comparator<? super E> comp)
public PriorityQueue(Collection<? extends E> coll)
public PriorityQueue(SortedSet<? extends E> coll)
public PriorityQueue(PriorityQueue<? extends E> coll)
• A capacidade é ilimitada, mas o ajustamento é
computacionalmente pesado.
LEEC@IST
Java – 73/83
Classe PriorityQueue (4)
public class Task {
String name; // identificador
int level;
// prioridade
public int level() {
return level;
}
public void newLevel(int value) {
level = value;
}
public Task(String name, int l) {
this.name=name;
level = l;
}
}
LEEC@IST
Java – 74/83
Classe PriorityQueue (5)
private static class TaskComparator implements Comparator<Task> {
public int compare(Task l, Task r) {
return l.level() – r.level();
}
}
LEEC@IST
Java – 75/83
Classe PriorityQueue (6)
PriorityQueue<Task> pq =
new PriorityQueue<Task>(10,new TaskComparator());
Task t;
for (char letter='A';letter<='G';letter++)
pq.add(new Task("Task "+letter,((letter-'A')%4));
while (!pq.isEmpty()){
t=pq.poll();
System.out.println(t.toString()+" priority=“+t.level());
}
No terminal é impresso:
LEEC@IST
Tarefa
Tarefa
Tarefa
Tarefa
Tarefa
Tarefa
Tarefa
A
E
B
F
C
G
D
prioridade=0
prioridade=0
prioridade=1
prioridade=1
prioridade=2
prioridade=2
prioridade=3
Java – 76/83
Interface Map (1)
• A interface Map<K,V> não estende a interface
Collection.
• Principais caracteristicas dum Map<K,V>:
– Não são adicionados elementos a um mapa,
mas sim um par chave/elemento.
– Um mapa permite aceder a um valor dada uma
chave.
– Uma chave mapeia zero ou um valor.
– Um valor pode ser mapeado por várias chaves.
• Um mapa estabelece uma função parcial de chaves
para valores.
LEEC@IST
Java – 77/83
Interface Map (2)
• Métodos básicos da interface Map<K,V>:
int size();
boolean isEmpty();
boolean containsKey(Object key);
boolean containsValue(Object value);
V get(Object key);
V put(K key, V value);
V remove(Object key);
void putAll(Map<? extends K, ? extends V> otherMap)
void clear();
LEEC@IST
Java – 78/83
Interface Map (3)
• Alguns métodos para ver Map<K,V> como
Collection:
Set<K> keySet();
Collection<V> values();
• Da interface Map são derivadas outras interfaces:
–SortedMap: chaves encontram-se ordenadas
–ConcurrentMap
LEEC@IST
Java – 79/83
Classe HashMap (1)
• A classe HashMap é uma implementação da
interface Map por uma tabela de dispersão.
• O desempenho é muito bom.
• Construtores da classe HashMap:
public
public
public
public
LEEC@IST
HashMap(int initialCapacity, float loadFactor)
HashMap(int initialCapacity)
HashMap()
HashMap(Map<? extends K, ? extends V> map)
Java – 80/83
Classe HashMap (2)
import java.util.*;
String str;
Long l;
Map store = new HashMap(); // nome usado como chave
str = “Miguel”; l = new Long(1327);
store.put(str,l);
l = (Long) store.get(str);
if (l!=null)
System.out.println(“Codigo de ”+str+“=”+l.longValue());
str = “Luisa”; l = new Long(9261);
store.put(str,l);
l = (Long) store.get(str);
if (l!=null)
System.out.println(“Codigo de ”+str+“=”+l.longValue());
LEEC@IST
Java – 81/83
Interface SortedMap
interface SortedMap<K,V> extends Map<K,V> {
Comparator<? super K> comparator();
K firstKey();
K lastKey();
SortedMap<K,V> subMap(K minKey, K maxKey);
SortedMap<K,V> headMap(K maxKey);
SortedMap<K,V> tailMap(K minKey);
}
LEEC@IST
Java – 82/83
Class TreeMap
• A classe TreeMap é uma implementação da
interface SortedMap por uma árvore binária
balanceada.
– O acesso é menos eficiente.
– Mas os elementos estão sempre ordenados.
• No programa exemplo de HashMap apenas se
substitui a declaração:
Map store = new TreeMap();
LEEC@IST
Java – 83/83
Download