Monday, September 28, 2009

[O Menino Amarelo] O Cativeiro Mofado

Era uma vez, um menino amarelo. E o menino amarelo estava namorando. A namorada do menino amarelo já havia tido filho, e era (como sempre) um tanto mais velha que o tal menino. Num desses finais de semana, a doida namorada do menino amarelo resolve convidá-lo para almoçar na casa dela...



Depois de andar do Himaláia até o Egito, passar em Angola e ir parar ali, pertinho do Bom Preço, eis que o menino chega suado na casa da namorada, sem fôlego sequer pra abrir um portão. E ali estava a criatura. A cria da maluca. Criança simples, sorridente, sentada no sofá da sala assistindo TV, analisando a amarelidão em pessoa com o mesmo jeito de um Poodle (e o menino amarelo ficou com trauma de Poodles depois que um quase mordeu seu rosto).



Comida diferente, sobremesa, sabe aquela média que namorada faz quando quer agradar? Pois bem. Ai vem aquela tapeada pra deixar o menino ambientado, pra acostumar a cria da maluca com o amarelo... Até que ela resolve despachar a cria pra Deus sabe onde. Leva até um pouco de sobremesa junto, pra tapear... Enfim sós. Ah, se ele soubesse... O tempo passa, e mais ou menos 3 ou 4 horas depois, batidas na porta. A maluca havia dito que estaria sozinha, então, a adestradora, junto com a cria da maluca e outra cria enxotada a tiros de um circo de horrores resolvem lhe fazer uma visita. Ambos ficaram desesperados, e no meio de tanta correria, a única idéia que a maluca teve foi trancafiar o menino amarelo num quarto mofado. Nãããããããooooooo!



Todo mundo sabe que o menino amarelo tem alergia a mofo. Mais amarelo do que nunca (quase um verde cana), até que tentou respirar devagar pra não inalar tanto mofo, mas depois de um certo tempo, a idéia não deu muito certo. Enquanto isso, a criatura vinda do circo dos horrores vasculha tudo em todos os aposentos, exceto aquele, que está trancado. Parecia até farejar cheiro de meia com chulé (era o sapato amarelo, mas tudo bem). E o Poodle até que não mostrou os dentes, ficou quietinho...



Diante do amarelo, havia uma janela. Gradeada por fora, mas era uma fresta de ar... E ali ele ficou feito peixe em rio poluído até a cavalaria do apocalipse ir embora... E que alívio... Parecia aquelas cenas de filme quando o navio afunda e há alguma câmara de ar, e os náufragos tomam o último fôlego antes de ir até a superfície, 150 metros acima...



Creative Commons License

Esta obra está licenciada sob uma Licença Creative Commons.

Monday, September 21, 2009

[Vimeo] Origami - In the Pursuit of Perfection

De bobeira, inventei de ir catar alguns videos no Vimeo. Afinal de contas, não é só o Youtube que tem coisa boa. Acabei achando essa animação bacaninha sobre origamis. Sem legenda, mas vale a pena :P



Origami In the Pursuit of Perfection from MABONA ORIGAMI on Vimeo.

Creative Commons License

Esta obra está licenciada sob uma Licença Creative Commons.

Thursday, September 17, 2009

[+18] FUUUUUU - salto mortal

Depois dessa, eu JURO que NUNCA mais dou salto mortal de escadas, pedras, ou seja lá que poha for, mesmo que seja a menos de 1 metro de altura!









UPDATE: Tiraram o video do ar no vimeo, mas achei em outro lugar.



Creative Commons License

Esta obra está licenciada sob uma Licença Creative Commons.

Thursday, September 3, 2009

SCJP - 07 - Collections [parte 02]

Bem, eu pensava que os termos order e sort em inglês significavam a mesma coisa, mas a gente já sabe que isso não é verdade. Vimos duas interfaces úteis para definir o modo como objetos devem ser ordenados numa coleção. E agora, como faço a ordenação, de fato?



Ordenando Coleções



Tome o seguinte trecho de código, onde tentamos ordenar uma certa lista de pessoas:



import java.util.*;
import java.io.*;

class Pessoa {
private String nome;

public Pessoa (String nome){
this.nome = nome;
}

public String getNome() {
return this.nome;
}

public void setNome(String nome){
this.nome = nome;
}

public String toString() {
String result = "nome: " + this.nome;
return result;
}
}

public class Principal {
public static void main(String[] args){
List<Pessoa> listaPessoa = new ArrayList<Pessoa>();
listaPessoa.add(new Pessoa("Fulano"));
listaPessoa.add(new Pessoa("Cicrano"));
listaPessoa.add(new Pessoa("Beltrano"));

Collections.sort(listaPessoa);
System.out.println(listaPessoa);
}
}


Note que não definimos qualquer ordenação natural, como no post anterior. Ao tentar compilar este código, temos o seguinte:





Se consultarmos a api do Java para este método, veremos que:



static <T extends Comparable<? super T>>
void sort(List<T> list)


É meio confuso ler esta assinatura de método, mas perceba que a lista que o método recebe é parametrizada. E o parâmetro é uma classe que deve implementar a interface Comparable. Mais precisamente, qualquer subclasse para qual exista uma superclasse que implemente esta interface.



Existe uma sobrecarga deste método, que recebe uma instância de Comparator:



static <T> void sort(List<T> list, Comparator<? super T> c) 


Também vimos como definir um Comparator no post anterior. O mais interessante, é que podemos instanciar um Comparator e definir o método de comparação ai mesmo, na passagem de parâmetros, ao invés de se criar uma classe específica. Isto é recomendado apenas se esta instância de comparator, com este critério de ordenação, for utilizado somente uma vez:



Collections.sort(listaPessoa, new Comparator<Pessoa>() {
public int compare(Pessoa a, Pessoa b) {
return a.getNome().compareTo(b.getNome());
}
});


Existem coisas interessantes como definir uma ordem inversa à ordem natural, de maneira extremamente simples. Para isso, usa-se o método estático Collections.reverseOrder(), que retorna uma instância de Comparator. Este método deve ser usado se a sua classe implementa a interface Comparable. Caso este não seja o caso, e já exista uma implementação de Comparator, use Collections.reverseOrder(Comparator<T> cmp). Pense como se estes métodos retornassem o resultado dos métodos que já vimos anteriormente, multiplicados por -1.



Ordenando Arrays



Assim como vimos a classe utilitária Collections para a ordenação de coleções, existe também a classe utilitária Arrays, com os mesmos métodos de ordenação: o que espera listas cujo tipo parametrizado é uma instância de Comparable, e o que espera uma instância de Comparable como definição de ordenação. Em adição, existem diversos métodos sobrecarregados iguais a esses, contemplando cada tipo primitivo (char, byte, short, int, boolean, float, double - esqueci de algum?). E mais: para esta classe utilitária, em especial, existem métodos que nos permitem ordenar apenas uma parte do array de valores. Vale dar uma conferida rápida na api desta classe.



Buscas em Coleções



Um dos métodos mais eficientes e mais conhecidos para buscas é a pesquisa binária. A classe utilitária Collections possui um método chamado binarySearch, que contempla este tipo de pesquisa:



static <T> int
binarySearch(List<? extends Comparable<? super T>> list,
T key)

static <T> int
binarySearch(List<? extends T> list, T key,
Comparator<? super T> c)


Note que ambos os métodos esperam uma lista, pelos motivos que veremos logo a seguir.





Fluxograma extraído da Wikipedia


Entretanto, é importante seguir algumas regras:



  • Buscas com sucesso retornam o índice do elemento procurado na lista passada pro parâmetro (para que o objeto possa ser resgatado usando o método get(int index) da lista).

  • Buscas sem sucesso retornam um valor negativo, que pode ser encarado cmo a posição de inserção do novo elemento da lista. Por ser um valor negativo (já que 0 é uma posição válida dentro da lista), a primeira posição de inserção válida é -1. Então, este número deve ser "transformado" para um valor positivo através do cálculo (-<ponto de inserção> - 1).

  • A coleção deve ser ordenada antes de se efetuar qualquer busca.

  • Se a coleção for ordenada utilizando determinado método de classificação (natural - implementando a interface Comparable - ou algum específico - implementando a interface Comparator), as buscas devem ser feitas utilizando exatamente o mesmo método de classificação.



O não uso da mesma estratégia de classificação na busca e na ordenação, ou a não ordenação da coleção antes da busca pode tornar os resultados da busca imprevisiveis.



Buscando em Arrays



Novamente, existem métodos similares aos citados para buscas nas coleções na classe utilitária Arrays. As regras para o uso destes métodos são as mesmas que as citadas para as coleções. Também existem sobrecargas desses métodos para cada primitiva existente, bem como sobrecargas para que buscas sejam efetuadas apenas numa parte do array. Para dúvidas, consultar a api.



Curiosidades sobre métodos de busca



A despeito do conhecimento da maioria, existe um tipo de busca chamado de Busca por Interpolação, que é mais eficiente que a busca binária. Isso porque o algoritmo utiliza interpolação linear para meio que "adivinhar" a posição do elemeto procurado, no caso de elementos uniformemente distribuídos. Vale a pena dar uma olhada, a título de informação.



Creative Commons License

Esta obra está licenciada sob uma Licença Creative Commons.

Wednesday, September 2, 2009

SCJP - 07 - Collections [parte 01]

E lá vou eu, ainda estudando muito pouco sobre a certificação. Mas aos poucos a gente vai lendo, e pelo menos tem noção do que é cobrado ou não no exame. Hoje, o assunto são as coleções do Java 6.



Esta imagem, retirada do livro da SCJP 6, demonstra bem o que a api fornece em termos de classes, interfaces e utilitarios:





Pelo diagrama de classes exibido acima, já podemos esclarecer algo importante: Nem todas as classes concretas herdam de Collection. É o caso, obviamente, das classes utilitárias (Collections e Arrays), e de todas as classes/interfaces relacionadas a Map (SortedMap, HashMap, Hashtable, TreeMap, LinkedHashMap e NavigableMap). Lembre-se disso ao tentar fazer conversões (cast) entre estes tipos.



Existem quatro comportamentos básicos, como também é visto no diagrama acima: as listas (List), os conjuntos (Set), os mapas (Map) e as filas (Queue). Falando dos mais complexos: os mapas relacionam uma chave, que pode ser qualquer coisa (desde que herde de Object) com um valor qualquer (também herdando de Object). Assim, vc pode mapear Integers em Strings, Strings em outros Maps, e por ai vai. As filas funcionam como uma lista de prioridades, ora implementadas como FIFO (first-in-first-out, ou primeiro a entrar é o primeiro a sair) ou como LIFO (last-in-first-out, ou ultimo a entrar é o primeiro a sair, também conhecido como pilha ou stack).



Existem também dois conceitos chave no que se refere a coleções em Java: ordenação e classificação. Existem coleções não ordenadas e não classificadas, coleções ordenadas e não classificadas, e coleções ordenadas e classificadas. Não existem coleções classificadas e não ordenadas, porque classificação é um tipo específico de ordenação. Qual a diferença entre um e outro? Até eles admitem que é um tanto confuso :P



Ordenação e Classificação



Ordenação se refere a como os elementos lhe são apresentados durante uma iteração sobre a coleção. Ao iterar sobre uma coleção, você espera encontrar elementos dispostos em uma ordem (não randômica). Algumas coleções mantém a ordem dos elementos baseadas num índice, outras baseadas no método de inserção (sempre ao final, por exemplo).



Classificação é um tipo de ordenação que toma por base propriedades do próprio objeto. A mais comum é a classificação natural, como por exemplo a alfabética ou a numérica. Quando não existe uma classificação natural para os objetos de uma classe, é preciso definí-la programaticamente, usando uma de duas alternativas: as interfaces Comparable e Comparator.



Para a primeira das alternativas, as classes passivas de classificação devem implementar a interface Comparable, que exige apenas a implementação do método compareTo().



public class Pessoa implements Comparable<Pessoa> {
private String nome;
...
public int compareTo(Pessoa pessoa) {
//Lembrando que String implementa Comparable
return this.getNome().compareTo(pessoa.getNome());
}
}


O contrato para este método é:

  • Deve ser um método público, retornar um inteiro primitivo, e receber como parâmetro, um objeto da própria classe.

  • Retorne 0, se o objeto em questão for logicamente igual que o objeto passad como parâmetro.

  • Retorne um inteiro negativo, se o objeto em questão for logicamente menor que o objeto passado como parâmetro.

  • Retorne um inteiro positivo, se o objeto em questão for logicamente maior que o objeto passado como parâmetro



Para a segunda alternativa, é preciso criar uma classe em separado, que implemente a interface Comparator:



import java.util.*;
public class PessoaComparator implements Comparator<Pessoa> {
public int compare(Pessoa a, Pessoa b) {
//Lembrando que String implementa Comparable
return a.getNome().compareTo(b.getNome());
}
}


O que diferencia uma da outra, em termos do contrato de implementação, é apenas a assinatura do método: precisa receber duas instâncias da classe passível de classificação. A lógica de retorno é a mesma definida para a interface Comparable.



Uma observação importante, é que devemos (ou deveríamos) verificar se os objetos são mutuamente comparáveis. Geralmente, não gostaríamos que fosse possível comparar instâncias de Pombo e Jacare, por exemplo. Isso só deve acontecer em casos bem específicos.



Creative Commons License

Esta obra está licenciada sob uma Licença Creative Commons.