sábado, 21 de novembro de 2009

Framework Collections do Java ==Coleções ou Estruturas de Dados Reutilizaveis --Parte 1




Framework Collections

Uma coleção - às vezes chamada de container - é simplesmente um objeto que agrupa múltiplos elementos em uma única unidade. As coleções são utilizados para armazenar, recuperar, manipular e comunicar dados agregados. Normalmente, eles representam itens de dados que formam um grupo natural, como uma mão de poker (uma coleção de cartas), uma pasta de correio (uma coleção de cartas), ou uma lista telefônica (mapeamento de nomes para números de telefone).

Se você já usou a linguagem de programação Java - ou praticamente qualquer outra linguagem de programação - você já está familiarizado com coleções. Implementações de Collection em anteriores (pré-1,2) versões da plataforma Java incluído Vector, Hashtable, e arrays. No entanto, essas versões não contêm um quadro coleções.


Um o framework de coleções é uma arquitetura unificada para representação e manipulação de coleções. Todo framework de coleções deve conter o seguinte:

  • Interfaces: Estes são os tipos de dados abstratos que representam coleções. Interfaces permitem coleções a serem manipuladas independentemente dos detalhes de sua representação. Em linguagens orientadas a objeto, interfaces geralmente formam uma hierarquia.

  • Implementações: Estas são as implementações concretas da coleção de interfaces. Em essência, eles são estruturas de dados reutilizáveis.

  • Algoritmos: Estes são os métodos que executam computações úteis, tais como busca e ordenação nos objetos que implementam as interfaces de coleta. Os algoritmos devem ser polimórficos, ou seja, o mesmo método pode ser usado em muitas implementações diferentes da interface de coleta apropriado. Em essência, os algoritmos de funcionalidade são reutilizáveis.


O Java Collections Framework fornece os seguintes benefícios ao programador:

  • Reduz o esforço de programação: Ao fornecer estruturas de dados e algoritmos úteis, com o Framework Collections você esta livre para concentrar-se as partes importantes de seu programa e não na parte de baixo nível "infraestrutura" necessária para faze-lo funcionar. Ao facilitar a interoperabilidade entre APIs não relacionadas, o Java Collections Framework te deixa livre para de escrever objetos ou adaptador de conversão de código para conectar-se API.

  • Aumenta a performance do programa e da qualidade: Framework Collections oferece alto desempenho, com implementações de alta qualidade contando com estruturas de dados úteis e algoritmos. As várias implementações de cada interface são substituíveis, assim que os programas podem ser facilmente ajustado trocando implementações coleção. Porque você está livre da labuta de escrever suas próprias estruturas de dados, você terá mais tempo para se dedicar a programas de melhoria da qualidade e desempenho.

  • Permite a interoperabilidade entre APIs não relacionadas: As interfaces de coleta são o vernáculo pelo qual APIs passar coleções frente e para trás. Se a minha administração de rede API fornece uma coleção de nomes de nó e se o seu kit de ferramentas GUI espera uma coleção de títulos de coluna, nossas APIs irá interoperar, mesmo que eles foram escritos de forma independente.

  • Reduz o esforço para aprender e usar novas APIs: APIs Muitos, naturalmente, tomar coleções na entrada e fornecer-lhes a saída. No passado, cada uma API, como tinha um pequeno sub-API dedicada a manipular suas coleções. Houve pouca consistência entre estes ad hoc sub-coleções APIs, assim que você teve para aprender cada um a partir do zero, e era fácil cometer erros quando utilizá-los. Com o advento das interfaces de recolha normal, o problema foi embora.

  • Reduz o esforço para conceber novas APIs: Este é o outro lado da vantagem anterior. Designers e implementadores não tem que reinventar a roda a cada vez que criar uma API que conta com coleções, em vez disso, eles podem usar as interfaces padrão coleção.

  • Reutilização de software Fosters: Novas estruturas de dados que estejam em conformidade com as interfaces padrão coleção são, por natureza reutilizável. O mesmo vale para novos algoritmos que operam sobre os objetos que implementam essas interfaces.


Interfaces


As interfaces principais do framework collection encapsulam diferentes tipos de coleções. Estas interfaces permitem que coleções sejam manipuladas independentemente dos detalhes de sua implementação. Tais Interfaces são a base do Java Collections Framework. Como você pode ver na figura seguinte, as interfaces principais formam uma hierarquia.





Por exemplo, Set é um tipo de coleção, SortedSet é um tipo especial de Set e assim por diante.Temos que notar tambem, que a figura possui 2 hierarquias diferentes, ja que Map nao é de fato uma verdadeira Collection!



  • Set-uma coleção que não pode conter elementos duplicados. Este modelo de interface a abstração matemática definida são usados para representar conjuntos, tais como as cartas que compreendem uma mão de poker, os cursos que compõem a grade de um aluno, ou os processos em execução em uma máquina

  • List-uma coleção ordenada (algumas vezes chamado de seqüência). As listas podem conter elementos duplicados. O usuário de uma lista geral, tem um controle preciso sobre onde cada elemento é inserido na lista e pode acessar elementos pelo seu índice inteiro (posição). Se você já usou Vector, você está familiarizado com o sabor das listas em geral.

  • Queue-uma coleção usada para armazenar vários elementos, antes de serem processados, por exemplo. Além de operações básicas de Collection, uma fila provê operações especiais de uma fila como a inserção, extração e inspeção. As filas normalmente, mas não necessariamente, guardam seus elementos atraves da politica FIFO (first-in, first-out) As exceções são as filas de prioridade, onde os elementos sao ordenados de acordo com um comparador fornecido, ou sua "ordenação natural. Qualquer que seja a ordenação utilizada, o primeiro de fila é o elemento que ira ser removido por uma chamada paos metodos remove ou poll. Em uma fila FIFO, todos os novos elementos são inseridos na cauda da fila. Outros tipos de filas podem usar regras de posicionamento diferentes. Cada implementação da fila deve especificar as suas propriedades de ordenação.
  • Map-um objeto que mapeia chaves para valores. Um mapa não pode conter chaves duplicadas: cada chave pode mapear para, no máximo, um valor. Se você já usou Hashtable, você já está familiarizado com os princípios de um Mapa

Implementações




Existem três implementações de Set com proposito geral- HashSet, TreeSet, e LinkedHashSet. Para as três , a utilização é geralmente simples. HashSet é muito mais rápido do que TreeSet (constante de tempo em função de log-tempo para a maioria das operações), mas não oferece garantias de ordenação. Se você precisa usar as operações na interface SortedSet, ou se a ordenação dos elementos é necessária, use TreeSet caso contrário use HashSet . É uma aposta justa que você vai acabar usando HashSet na maior parte do tempo.


Existem duas implementações com finalidades gerais de List - ArrayList e LinkedList. Na maioria das vezes, você provavelmente vai usar ArrayList, que oferece tempo constante de acesso e de posicionamento sendo simplesmente rápido. Ele não tem que alocar um objeto nó para cada elemento da lista, e pode tirar vantagem de System.arraycopy quando tem que movimentar vários elementos ao mesmo tempo. Pense em ArrayList como um vetor sem a sobrecarga de sincronização.

Se você freqüentemente adiciona elementos no início da lista ou itera na lista para eliminar os elementos do seu interior, você deve considerar usar LinkedList. Essas operações exigem tempo constante em um LinkedList e tempo linear em um ArrayList. Mas você paga um preço grande no desempenho. Acesso posicional requer tempo linear em uma LinkedList e constante em um ArrayList. Além disso, o fator constante para LinkedList é muito pior. Se você acha que quer usar uma LinkedList, meça o desempenho de seu aplicativo tanto com LinkedList como com ArrayList antes de fazer sua escolha; ArrayList é geralmente bem mais rápido.

As implementações de finalidade geral de Map são HashMap, TreeMap e LinkedHashMap. Se você precisa de operações como as de SortedMap ou necessita de uma iteração Collection-view, utilize TreeMap , se você quiser velocidade máxima e não se preocupa com a ordem de iteração, HashMap é a sua escolha, se você quiser um desempenho próximo de HashMap e inserção-iteração com ordem, LinkedHashMap sera a escolha.

LinkedHashMap fornece duas capacidades que não estão disponíveis em um LinkedHashSet. Quando você cria um LinkedHashMap, você pode requisitá-lo com base na chave de acesso ao invés de inserção. Em outras palavras, apenas olhando para o valor associado com uma chave que traz a chave para o final do mapa. Além disso, LinkedHashMap fornece o método removeEldestEntry, que pode ser substituído para impor uma política de remoção de mapeamentos obsoletos automaticamente quando novos mapeamentos são adicionados ao mapa. Isto torna muito fácil de implementar um cache personalizado.



LinkedList implementa a interface Queue, fornecendo um fila FIFO com operações para adicionar, remover da fila e assim por diante.

A classe PriorityQueue é uma fila de prioridades com base na estrutura de dados Heap. Essa fila de elementos é ordenada de acordo com uma ordem especificada no momento da construção, que podem ser os elementos "naturais ordenação ou a ordem imposta por um comparador explícito.

Na fila existemas seguintes de operações de recuperação - poll, remove, peek, e element - para acessar o elemento na frente da fila. A cabeça da fila é o menor elemento que diz respeito à ordenação especificada. Se vários elementos estão ligados pelo valor, a cabeça é um desses elementos, os empates são resolvidos de forma arbitrária.

PriorityQueue e seu iterador implementam todos os métodos opcionais da coleção e Iterator interfaces. O iterador previsto no iterador método não é garantido para percorrer os elementos da PriorityQueue em qualquer ordem particular. Se você precisa de condenação na iteração, considere o uso Arrays.sort (pq.toArray ()).



O framework Collections do Java é um tema simples, porem extenso e existem ainda muito mais informações que eu gostaria de compartilhar , por isso não percam os proximos posts, mostrando como funcionam os algoritmos de ordenação, shuffle, e uma serie de algoritmos muito uteis para se trabalhar com coleções, alem de particularidades da API e como usar coleções concorrentes ou thread-safe e criaremos uma coleção Wrapper para uma matriz quadrada com operações basicas de algebra linear, como exemplo.Outro tema muito abordado em conjunto é Generics(Genericos) ao qual falarei tambem em uma outra oportunidade.


Referencias

Marcadores: , , , , ,

Não generalize, pois existem muitas exceções a regra!



"Uma exceção é um evento, que ocorre durante a execução de um programa, que interrompe o fluxo normal das instruções do programa."


Quando um erro ocorre dentro de um método, o método cria um objeto e manda-opara o sistema de execução(Runtime). O objeto, chamado de um objeto de exceção(Exception), contém informações sobre o erro, incluindo seu tipo e o estado do programa quando ocorreu o erro(StackTrace). Criando um objeto de exceção e entregá-lo para o sistema de execução é chamado de lançar(throw) uma exceção.

Depois de um método gerar uma exceção, o sistema de execução tenta achar alguem para lidar com a exceção. O conjunto de possíveis "algumas coisas" para tratar a exceção é a lista ordenada de métodos que tinha sido chamado para chegar ao método onde ocorreu o erro. A lista de métodos é conhecido como a pilha de chamadas (ver figura seguinte).




O sistema de tempo de execução procura a pilha de chamadas para um método que contém um bloco de código que pode manipular a exceção. Este bloco de código é chamado um manipulador de exceção. A busca começa com o método em que ocorreu o erro e continua através da pilha de chamadas na ordem inversa em que os métodos foram chamados. Quando um manipulador apropriado seja encontrado, o sistema de execução passa a exceção para o manipulador. Um manipulador de exceção é considerado adequado se o tipo do objeto de exceção acionada coincide com o tipo que pode ser tratada pelo manipulador.

O manipulador de exceção escolhido é dito para capturar a exceção. Se o sistema de execução de forma exaustiva procura um manipulador para exceção na pilha de chamadas, sem encontrar um manipulador de exceção apropriado, como mostrado na figura ao lado, o sistema de execução (e, conseqüentemente, o programa) é encerrado(A thread principal no programa, que roda o main, morre, pois nao "abriu o paraquedas"!).


Basicamente existem 3 tipos de exceções que podem ocorrer na JVM:

O primeiro tipo de exceção é a exceção verificada(checked). Estas são as condições excepcionais que uma aplicação bem escrita deve antecipar e recuperar. Por exemplo, suponha que um aplicativo solicita a um usuário para escrever um nome de arquivo de entrada, em seguida, abre o arquivo, passando o nome para o construtor para java.io.FileReader. Normalmente, o usuário fornece o nome de um arquivo, de forma legível, para a construção do objeto FileReader bem-sucedido, e para a execução do aplicativo continua normalmente. Mas às vezes o usuário fornece o nome de um arquivo inexistente, e o construtor lança(throws) um objeto java.io.FileNotFoundException. Um programa bem escrito vai pegar essa exceção e notificar o usuário do erro, possivelmente levando a um nome de arquivo corrigido.

O segundo tipo de exceção é o erro(error). Estas são as condições excepcionais que são externas ao aplicativo, e que a aplicação normalmente, a qual o programa não pode se antecipar ou se recuperar. Por exemplo, suponha que uma aplicação com êxito abre um arquivo para a entrada, mas é incapaz de ler o arquivo por causa de um hardware ou mau funcionamento do sistema. A leitura mal feita jogará java.io.IOError. Um aplicativo pode optar por pegar essa exceção, a fim de notificar o usuário do problema - mas também pode fazer sentido para o programa para imprimir um rastreamento de pilha e sair,sendo sempre bo pratica a segunda opção.

Os erros não estão sujeitos à requerimentos do tipo "pegar ou especificar". Os erros são as exceções indicadas pelo erro e suas subclasses.

O terceiro tipo de exceção é a exceção de runtime. Estas são as condições excepcionais que são internas à aplicação, e que a aplicação normalmente, não pode antecipar ou recuperar. Estes geralmente indicam erros de programação, como erros de lógica ou de utilização indevida de uma API. Por exemplo, considere a aplicação descrita anteriormente que passa um nome de arquivo para o construtor para FileReader. Se um erro de lógica faz com que um nulo para ser passado para o construtor, o construtor irá lançar NullPointerException. O aplicativo pode pegar essa exceção, mas provavelmente faz mais sentido para eliminar o erro que causou a exceção para ocorrer.

Exceções de runtime tambem não estão sujeitos à requerimentos do tipo "pegar ou especificar".

Exceções de runtime são as indicadas pela classe RuntimeException e suas subclasses.

Erros e exceções de runtime são conhecidas coletivamente como exceções nao checadas(unchecked).


//Note: Essa classe nao compila por design!
//O codigo abaixo mostra diversas má praticas de design
//,porem tem carater meramente didático para o tema do post
import java.io.*;
import java.util.Vector;

public class ListOfNumbers {

private Vector vector;
private static final int SIZE = 10;

public ListOfNumbers () {
vector = new Vector(SIZE);
for (int i = 0; i < SIZE; i++) {
vector.addElement(new Integer(i));
}
}

public void writeList() {
PrintWriter out = new PrintWriter(
new FileWriter("OutFile.txt"));

for (int i = 0; i < SIZE; i++) {
out.println("Value at: " + i + " = " +
vector.elementAt(i));
}

out.close();
}
}



O construtor inicializa um fluxo de saída em um arquivo. Se o arquivo não pode ser aberto, o construtor lança uma IOException. Aposisso, uma chamada ao método elementAt a classe Vector, que gera uma ArrayIndexOutOfBoundsException se o valor de seu argumento é muito pequeno (inferior a 0) ou muito grande (mais do que o número de elementos contidos no momento por vetores).

Se você tentar compilar a classe ListOfNumbers, o compilador imprime uma mensagem de erro sobre a exceção lançada pelo construtor FileWriter. No entanto, ele não exibir uma mensagem de erro sobre a exceção lançada pelo elementAt. A razão é que a exceção lançada pelo construtor, IOException, é uma exceção verificada(checked), e a acionada pelo método elementAt, ArrayIndexOutOfBoundsException, é uma exceção desmarcada(unchecked).

Agora que você está familiarizado com a classe ListOfNumbers e onde as exceções podem ser geradas dentro dela, você está pronto para escrever manipuladores de exceção para capturar e manipular as exceções.

Para construir um manipulador de exceção para o método da classe writeList ListOfNumbers, coloque o codigo que pod elançar uma exceção ,do método writeList dentro de um bloco try. Há mais do que uma maneira de fazer isso. Você pode colocar cada linha de código que pode lançar uma exceção dentro do seu próprio bloco try e fornecer manipuladores de exceção em separado para cada um. Ou, você pode colocar todo o código writeList dentro de um bloco único e tentar associar vários manipuladores com ele. A listagem a seguir usa um bloco try do método, pois todo o código em questão é muito curto.


//...codigo omitido
private Vector vector;
private static final int SIZE = 10;

PrintWriter out = null;

try {
System.out.println("Entered try statement");
out = new PrintWriter(new FileWriter("OutFile.txt"));
for (int i = 0; i < SIZE; i++) {
out.println("Value at: " + i + " = "
+ vector.elementAt(i));
}
}
// catch e finally



Se ocorrer uma exceção dentro do bloco try, essa exceção é tratado por um manipulador de exceção a ela associados. Para associar um manipulador de exceção com um bloco try, você deve colocar um bloco catch depois do bloco try..


try {

} catch (ExceptionType name) {

} catch (ExceptionType name) {

}


Cada bloco catch é um manipulador de exceção e manipula o tipo de exceção indicada pelo seu argumento. O tipo de argumento, ExceptionType, declara o tipo de exceção que o manipulador pode manipular e deve ser o nome de uma classe que herda da classe Throwable. O manipulador pode referir-se a exceção com o nome.

O bloco catch contém código que é executado, se e quando o manipulador de exceção é invocado. O sistema de execução chama o manipulador de exceção quando o manipulador é o primeiro na pilha de chamadas cuja ExceptionType corresponde ao tipo da exceção lançada. O sistema considera que é um jogo jogado, se o objeto pode ser legalmente atribuído ao argumento do manipulador de exceção.

Seguem dois manipuladores de exceção para o método writeList - um para dois tipos de exceções verificadas que podem ser jogadas dentro da declaração try.




try {

} catch (FileNotFoundException e) {
System.err.println("FileNotFoundException: "
+ e.getMessage());
throw new SampleException(e);

} catch (IOException e) {
System.err.println("Caught IOException: "
+ e.getMessage());
}



Ambos os manipuladores imprimem uma mensagem de erro. O segundo manipulador faz mais nada. Pela captura de qualquer IOException que não é capturada pelo primeiro manipulador , ele permite que o programa continue executando.
O primeiro manipulador, além de imprimir uma mensagem, gera uma exceção definida pelo usuário. Neste exemplo, quando o FileNotFoundException é pego, ele cria uma exceção definida pelo usuário chamado SampleException para ser acionada. Você pode querer fazer isso se você quiser que o seu programa possa tratar uma exceção desta situação de uma maneira específica.

Manipuladores de exceção podem fazer mais do que apenas imprimir mensagens de erro ou parar o programa. Eles podem fazer a recuperação de erro, solicitar que o usuário tome uma decisão, ou propagar o erro até um manipulador de nível superior com exceções em cadeia.


Um bloco finally sempre é executado quando um bloco try ou catch retorna. Isso garante que o bloco finally será executado mesmo se ocorrer uma exceção inesperada. Mas, finalmente, é útil para mais do que apenas a manipulação de exceção - que permite o programador para evitar que um código de limpeza de recursos acidentalmente seja contornado por um return, continue, ou break. Colocar código de limpeza em um bloco finally é sempre uma boa prática, mesmo quando não há exceções são previstas.


Importante: O bloco finally é um instrumento fundamental para a prevenção de vazamentos de recursos. Ao fechar um arquivo ou recuperação de recursos, colocar o código em um bloco finally para garante que o recurso é sempre recuperado.


//metodo completo apos o refactoring para inserir tratamento de exceções!

public void writeList() {
PrintWriter out = null;

try {
System.out.println("Entering try statement");
out = new PrintWriter(
new FileWriter("OutFile.txt"));
for (int i = 0; i < SIZE; i++)
out.println("Value at: " + i + " = "
+ vector.elementAt(i));

} catch (ArrayIndexOutOfBoundsException e) {
System.err.println("Caught "
+ "ArrayIndexOutOfBoundsException: "
+ e.getMessage());

} catch (IOException e) {
System.err.println("Caught IOException: "
+ e.getMessage());

} finally {
if (out != null) {
System.out.println("Closing PrintWriter");
out.close();

}
else {
System.out.println("PrintWriter not open");
}
}
}


Referências
Tutorial Oficial da Sun sobre Java, capitulo Exceptions

Artigos
Como lançar suas próprias exceções

Exceções de runtime, A Controversia


Espero ter ajudado com este post!
Obrigado pelo seu tempo!
Participem do OSUM, sua participação é o mais importante!

Marcadores:

Jython




Jython é uma implementação do alto nível, dinâmica, orientada a objetos da linguagem Python perfeitamente integrada com a plataforma Java. O antecessor de Jython, JPython, é certificada como 100% puro Java. Jython está disponível livremente tanto para fins comerciais e não-comerciais e é distribuído com código fonte. Jython é complementar ao Java e é especialmente indicado para as seguintes tarefas:



  • Scripts integrados - programadores Java podem adicionar as bibliotecas do Jython ao seu sistema para permitir que os usuários finais possam escrever scripts simples ou complicados que adicionem funcionalidade ao aplicativo.

  • Experimentação Interactive - Jython fornece um interpretador interativo que pode ser usado para interagir com os pacotes Java ou com o funcionamento de aplicações Java. Isso permite que os programadores para experimentar e depurar qualquer sistema Java usando Jython.

  • Desenvolvimento rápido de aplicações - programas em Python são tipicamente 2-10X menor que o programa em Java equivalente. Isto traduz-se diretamente ao aumento da produtividade do programador. A interação contínua entre Python e Java permite aos desenvolvedores livremente misturar as duas línguas, tanto durante o desenvolvimento e no transporte de produtos.



Em 2008 a SUN contratou os 2 desenvolvedores principais do projeto Jython, Ted Leung e Frank Wierzbicki para tornar o Jython uma escolha segura, potente e facil do Python para JVM.

Com isso a SUN reconheceu o poder e difusão da linguagem, ja usada por milhares de desenvolvedores no contexto Linux e web.No repositorio padrao do OpenSolaris ja encontramos o Python 2.2.4, e no Netbeans ja existe a integração com o Python, sendo um projeto futuro, transformar o Netbeans na IDE perfeita para a dobradinha Jython/Django assim como os sucessos de JRuby/Rails e Groovy/Grails, com a mesma eficiencia e pragmatismo.

Confira a entrevista para o developers.sun de Ted Leung e Frank Wierbicki

Existem inúmeras linguagens alternativas implementadas para a Java VM. Os recursos a seguir ajudam o Jython a ser separado do resto:



  • A compilação dinâmica de bytecodes Java - leva a melhor performance possível, sem sacrificar a interatividade.

  • Capacidade de estender as classes Java existentes em Jython - permite o uso eficaz de classes abstratas.

  • Opcional compilação estática - permite a criação de applets, servlets, beans,midlets,...

  • Bean Propriedades - fazer uso de pacotes Java facilmente.

  • Linguagem Python - combina poder notável com uma sintaxe muito clara. Ele também suporta um completo modelo de programação orientada a objetos o que o torna um ajuste natural para o projeto de Java OO, tornando aplicações Java mais poderosas em determinada situação.




Para participar ativamente da comunidade, nas palavras de Ted Leung e Frank Wierzbicki , desenvolvedores Jython na SUN:


  • Join the Jython project. I'm looking for folks who would be serious about contributing to a community-driven Python support module for NetBeans.

  • Join any of the other great Python projects, like Django, TurboGears, Twisted, pyglet, and so on.

  • Send Frank or me an email with your comments and suggestions. We'll probably set up something a bit more formal, but for now, our inboxes will do.



Alguns Links Interessantes:

Slide do JavaOne 2008 com os riadores do projeto dando dicas

Framework Web Agil similar ao Rails,usado por diversos sistemas como New York Times e sites da Google

Livro Dive in to Python, uma introdução basica sobre a linguagem

Python no Netbeans IDE

Site do projeto Jython

Grupo Jython OSUM


OBRIGADO PELO SEU TEMPO!

Marcadores: