Você está na página 1de 8

2.

Vectores
Já aprendemos arrays que são um meio simples e eficaz de manipular conjuntos de dados. A sua
principal limitação é que é necessário definir as suas dimensões no momento em que são criados.
Nem sempre isso é possível. Nestas situações, é preferível utilizar estruturas cuja dimensão se vai
adaptando às necessidades durante a execução do programa. Podem ser referidas como
estruturas dinâmicas, entre as quais os vectores e os dicionários.
Os vectores são semelhantes aos arrays, pois também podem conter um conjunto de objectos
aos quais é atribuído um índice. Existem três diferenças fundamentais entre arrays e vectores:
• Os vectores podem crescer ou decrescer de tamanho em função das necessidades do
programa;
• Os vectores apenas podem armazenar objectos, pelo que não é possível ter um vector
contendo apenas tipos simples (int, double, etc...). Só transformando estes valores em
objectos é que possível armazená-los num vector;
• Os elementos de um array têm que ser todos do mesmo tipo, que é indicado no momento
da sua criação. Pelo contrário, um vector pode conter elementos de diversos tipos, que
sejam objectos.
2.1. Criação e manipulação de um vector
Os vectores são objectos da classe predefinida Vector, que está incluída na biblioteca
java.util. Qualquer programa que utilize vectores tem que importar esta biblioteca:
import java.util.*;
Para criar um vector utiliza se seguinte instrução:
Vector nomeDeReferencia = new Vector();
Exemplo: Vector lista = new Vector();
Daqui resulta um objecto da classe Vector, referenciado por lista, que pode conter um
conjunto de objectos e que tem como definidos vários comportamentos que permitem manipular
esse conjunto.
Uma grande vantagem de um vector dinâmico em relação aos arrays é que ele possui vários
métodos para facilitar a realização de importantes operações
add(Objecto) adiciona o objecto no fim do vector. Devolve true;
add(indice,Objecto) insere o objecto na posição do vector indicada por indice;
addElement(Objecto) adiciona um objecto ao vector, aumentando o seu tamanho. É
identico na funcionalidade ao metodo add(Obj).É do tipo void;
elementAt(indice) devolve o objecto colocado na posição indicada por indice;
clear() elimina todos os elementos do vector;
contains(Objecto elem) verifica se determinado elemento está contido no vector;
indexOf(Objecto) devolve o índice da 1a posição onde se encontra um objecto
igual ao fornecido ou -1 se não encontrar;
isEmpty() verifica se o vector se encontra vazio;
remove(indice) remove o objecto armazenado na posição dada por indice;
setElementAt(Objecto,indice) define (set) o elemento na posição especificada pelo
indice pelo objecto fornecido;
size() devolve o número de elementos do vector.
Não se especifica a capacidade de um vector dinâmico no momento de sua criação e também não
é preciso definir ou alterar o seu tamanho antes da inclusão de novos elementos, tendo em vista
que ele crescerá, automaticamente, para abrigá-los, na medida em que forem sendo adicionados.
O tamanho de um vector pode ser consultado, a qualquer momento, invocando-se o seu método
size(). Ele retorna um número inteiro que representa a quantidade de elementos presentes.
Opcionalmente, o método isEmpty() pode ser invocado para testar se o vector encontra-se
vazio. Esse método retorna o valor boleano true se o vector estiver vazio e o valor boleano
false se ele contiver algum elemento.
Depois de adicionar todos os elementos desejados a um vector, é aconselhável invocar seu
método trimToSize(), que ajusta a sua capacidade para o seu tamanho actual, liberando o
espaço que estiver sendo ocupado desnecessariamente.
A inserção de novos elementos é feita através do método add(), que possui duas versões
distintas. Uma delas exige apenas um objecto como argumento, representando o objecto
que será inserido ao final do vector. A outra versão também exige um numero inteiro como
seu primeiro argumento, indicando a posição na qual o elemento será inserido. O segundo
argumento dessa versão também deve ser um objecto.
Note que a classe Vector não oferece métodos através dos quais seja possível incluir valores de
tipos primitivos porque ela representa vectores de objectos. No entanto, um valor de tipo primitivo
pode ser facilmente convertido em um objecto e posteriormente adicionado em um vector:
Vector v = new Vector();
v.add (new Boolean(true));
v.add (new Integer(1234));
v.add (new Double(123.4));
v.add (new Character('A'));
Outra forma de realizar essa tarefa é converter os valores de tipos primitivos em objectos da
classe String:
Vector v = new Vector();
v.add (String.valueOf(true));
v.add (String.valueOf(1234));
v.add (String.valueOf(123.4));
v.add (String.valueOf('A'));
Não há necessidade de qualquer conversão para variáveis de tipo String:
Vector v = new Vector();
v.add ("um texto");
Uma limitação importante dos vectores surge quando é necessário pesquisar um elemento
específico, por exemplo a ficha de um determinado estudante. O método indexOf() permite
desempenhar esta tarefa. No entanto, este método só localiza objectos que sejam réplicas
exactas do objecto que lhe é fornecido como parâmetro. Não basta fornecer um objecto com o
nome pretendido (no caso de Estudante), é necessário indicar todos os seus dados (nome,
notas e média). Esta é uma limitação relevante, porque, muitas vezes, os dados não são
completamente conhecidos e o objectivo é, precisamente, procurá-los. Os dicionários
(dictionary) já não apresentam esta limitação.
3. Ficheiros de objectos
Ficheiros são conjuntos organizados de dados armazenados em dispositivos de memória
permanente. Java considere cada ficheiro como um fluxo (stream em inglês) sequencial de bytes:
0 1 2 3 4 5 ... n-1 Marcador de fim de
... ficheiro

Cada ficheiro acaba com um marcador de fim de ficheiro ou em um número específico de bytes
registrado numa estrutura administrativa de dados mantida pelo sistema. Um programa Java abre
um ficheiro através de criação de um objecto e associação de um fluxo de bytes a este objecto.
Na verdade, Java cria três objectos de fluxo: System.in (permite que um programa insira bytes
pelo teclado), System.out (permite gerar como saída dados no ecrã) e System.err (permite
gerar como saída mensagens de erro no ecrã).
Os programas fazem processamento de ficheiros usando classes da biblioteca java.io, pelo que
esta deve ser importada para qualquer programa que as use.
A biblioteca java.io contém classes
• FileReader para entrada baseada em caracteres de um ficheiro e
• FileWriter para saída baseada em caracteres para um ficheiro
• FileInputStream para entrada baseada em bytes de um ficheiro e
• FileOutputStream para saída baseada em bytes para um ficheiro.
Os ficheiros são abertos criando-se objectos dessas classes de fluxo. Java oferece 58 classes
distintas para realizar entrada/saída. A hierarquia de classes de java.io é bastante grande e
relativamente complexa pois possui classes para o processamento de entrada e saída em
ficheiros de acesso sequencial, aleatórios e compactados.
Muitas vezes, os dados que se pretendem armazenar num ficheiro não são tão simples como as
cadeias de caracteres (que já aprendemos anteriormente), por exemplo, a informação
armazenada num objecto ou num array de objectos.
Manipulação de ficheiros de objectos
O método writeObject() da classe ObjectOutputStream serve para organizar os dados do
objecto, de modo a que possam ser enviados sequencialmente para o ficheiro através do fluxo de
saída de dados.
O método readObject() da classe ObjectInputStream recolhe os dados do fluxo de entrada
e reorganiza-os, de forma a reconstruir um objecto igual ao inicialmente escrito.
Estes métodos podem trabalhar com qualquer classe de objectos predefinidos na linguagem,
como sejam as cadeias de caracteres, os vectores ou os dicionários.
No caso do programador pretender armazenar em ficheiro objectos de classes definidas por si,
terá que indicar expressamente que autoriza a sua reorganização para armazenamento em
ficheiro. Para isso deve acrescentar ao cabeçalho dessas classes as palavras implements
Serializable, por exemplo:
public class Turma implements Serializable
Este cabeçalho permite que todos os objectos da classe Turma possam ser fornecidos ao método
writeObject() para serem enviados para um ficheiro. De igual modo, o método readObject()
pode ser usado para ler dados do ficheiro e construir um objecto correspondente em memória
central.
É importante notar que apenas as variáveis de instancia (atributos) de um objecto são incluídas
no ficheiro. As variáveis globais ou de classe que um objecto utilize não são incluídas no ficheiro,
dado que não são sua propriedade, mas sim da classe, podendo ser partilhadas por todos os
objectos dessa classe.
No caso dos ficheiros de texto, foram utilizadas as classes FileReader e FileWriter para
estabelecer os fluxos de dados, uma vez que se tratava apenas de caracteres. Neste caso, a
utilização destas classes não é adequada.
O processo de criação de fluxos de dados pode ser assegurado por:
FileInputStream fin = new FileInputStream (new File(nomeDoFich));
FileOutputStream fout = new FileOutputStream (new File(nomeDoFich));
Ou, abreviadamente:
FileInputStream fin = new FileInputStream (nomeDoFich);
FileOutputStream fout = new FileOutputStream (nomeDoFich);
Agora é possível criar objectos para manipular os ficheiros de objectos:
ObjectInputStream obin = new ObjectInputStream (fin);
ObjectOutputStream obout = new ObjectOutputStream (fout);
Se o ficheiro já existir, a instrução de abertura para escrita provoca o apagamento de todos os
dados nele existentes.

Exemplo:
import java.io.*;

public class Produto implements Serializable


{ private String artigo;
private int cod;
private double preco;
private boolean importado; //publica ou privada

public Produto(String artigo,int cod,double preco,boolean importado)


{ this.artigo = artigo;
this.cod = cod;
this.preco = preco;
this.importado = importado;
}

public Produto()
{ this("",0,0.0,false); }

public void setArtigo(String artigo){this.artigo = artigo;}


public void setCod(int cod){this.cod = cod;}
public void setPreco(double preco){this.preco = preco;}
public void setImportado(boolean tipo){this.importado = importado;}

public void lerDados()


{ System.out.print("Introd. o nome de produto: ");
artigo = Le.umaString();
System.out.println (artigo);
setArtigo(artigo);

System.out.print("Introd. o codigo do produto: ");


cod = Le.umInt();
System.out.println (cod);
setCod(cod);

System.out.print("Introd. o preco do produto: ");


preco = Le.umDouble();
System.out.println (preco);
setPreco(preco);

System.out.print("E um produto importado(s/n)?: ");


char resp = Le.umChar();
if (resp == 's' || resp == 'S')
importado = true;
else
importado = false;
System.out.println (resp);
setImportado(importado);
}

public String toString()


{ return "Artigo-> "+artigo+", cod: "+cod+",preco: "+preco+", importado:
"+importado;
}
}
---------------------------------------------------
public class Computador extends Produto
{ private String proces;
private int cont=0;
//construtor
public Computador(String artigo,int cod,double preco,boolean importado,
String proces)
{ super(artigo,cod,preco,importado);
this.proces = proces;
cont++;
}

public Computador() { this("",0,0.0,false,""); }


public void setProces(String proces) {this.proces = proces;}
public int getCont() {return cont;}

public String toString(){return super.toString()+",com processador: "+proces;}

public void lerDados()


{ super.lerDados();
System.out.print("Introd. o processador instalado: ");
proces = Le.umaString();
System.out.println (proces);
setProces(proces);
}
}
----------------------------------------------
public class Impressora extends Produto
{ private String marca;
private int cont=0;
//construtor
public Impressora(String artigo,int cod,double preco,boolean importado,String marca)
{ super(artigo,cod,preco,importado);
this.marca = marca;
cont++;
}

public Impressora() { this("",0,0.0,false,""); }

public void setMarca(String proces) {this.marca = marca;}


public int getCont() {return cont;}
public String toString() { return super.toString()+", de marca: "+ marca; }

public void lerDados()


{ super.lerDados();
System.out.print("Introd. a marca da impressora: ");
marca = Le.umaString();
System.out.println (marca);
setMarca(marca);
}
}
----------------------------------------------
public class Scanner extends Produto
{ private String resolucao;
private int cont=0;
//construtor
public Scanner(String artigo,int cod,double preco,boolean importado, String
resolucao)
{ super(artigo,cod,preco,importado);
this.resolucao = resolucao;
cont++;
}

public Scanner() { this("",0,0.0,false,""); }


public void setResolucao(String resolucao) {this.resolucao = resolucao;}
public int getCont() {return cont;}
public String toString(){return super.toString()+",de resolucao: "+resolucao;}

public void lerDados()


{ super.lerDados();
System.out.print("Introd. a resolucao: ");
resolucao = Le.umaString();
System.out.println (resolucao);
setResolucao(resolucao);
}
}
----------------------------------------------------
import java.util.*;
import java.io.*;

public class OrgVector


{ private Vector lista;
private int quantTot;

public OrgVector()
{ lista = new Vector();
quantTot=0;
}

public void criaElemComput()


{ Computador comp = new Computador();
comp.lerDados();
lista.addElement(comp);
quantTot += comp.getCont();
}

public void criaElemImpres()


{ Impressora impr = new Impressora();
impr.lerDados();
lista.addElement(impr);
quantTot += impr.getCont();
}

public void criaElemScanner()


{ Scanner scan = new Scanner();
scan.lerDados();
lista.addElement(scan);
quantTot += scan.getCont();
}

public int getQuantTotal()


{ return quantTot; }

public void esc_fich_Vector(String fich)


{ try
{ FileOutputStream dataFile = new FileOutputStream(fich);
ObjectOutputStream escrita = new ObjectOutputStream(dataFile);
escrita.writeObject(lista);
escrita.close();
} catch (IOException Erro) {System.out.println("Ficheiro nao existe");}
}

public void ler_fich_Vector(String fich)


{ try
{ FileInputStream dataFile = new FileInputStream(fich);
ObjectInputStream ler = new ObjectInputStream(dataFile);
lista = (Vector)ler.readObject();
ler.close();
} catch (Exception E){System.out.println("Ficheiro nao existe"); }
}

public String toString()


{ String vis= new String("\tDados armazenados no ficheiro:\n");
for (int n = 0; n < lista.size(); n++)
{ Produto prod = (Produto)lista.elementAt(n);
vis += prod.toString() + "\n";
}
return vis;
}
}
------------------------------------------------
public class Executavel
{ public static void main(String[] args)
{ OrgVector v = new OrgVector();
byte op; String nomeFich="";
do
{ do
{ System.out.println("\t1.Introduzir dados sobre Computaor");
System.out.println("\t2.Introduzir dados sobre Impressora");
System.out.println("\t3.Introduzir dados sobre Scanner");
System.out.println("\t4.Visualizar a quantidade total de equipamento");
System.out.println("\t5.Gravar no Ficheiro");
System.out.println("\t6.Ler do ficheiro e Visualizar");
System.out.println("\t7.SAIR");
System.out.print ("\tIntrod. Opcao: ");
op = Le.umByte();
System.out.println(op+"\n");
} while(op<1||op>7);
switch(op)
{ case 1: v.criaElemComput(); break;
case 2: v.criaElemImpres(); break;
case 3: v.criaElemScanner();break;
case 4: System.out.println("Foram processados dados de "+
v.getQuantTotal()+" produto(s)");break;
case 5: System.out.println("Introduza o nome do ficheiro: ");
nomeFich = Le.umaString();
v.esc_fich_Vector(nomeFich);
System.out.println("Ficheiro gravado com nome "+nomeFich);
break;
case 6: v.ler_fich_Vector(nomeFich);
System.out.println(v.toString()); break;
}
} while(op!=7);
}
}