55_Lambda

7
37 \ _lambda Você sabe ordenar uma lista? Sabe selecionar os elementos de uma lista a partir de um critério? E extrair os valores de uma determina- da propriedade do objeto de uma lista? São tarefas comuns que estamos cansados de repeti-las. Mas será que conhecemos a melhor forma de escrevê-las? Há como fazer de forma mais concisa, sem perder a legibilidade? Neste artigo vamos mostrar o que muda nessas tarefas do dia a dia ao utilizar bibliotecas como o Google Guava e LambdaJ, que adi- cionam um sabor funcional ao Java atual. Depois chegaremos ao futuro Java 8, para ver como o lambda e os defender methods estão mudando a linguagem em direção ao funcional. Chegando ao Lambda no Java 8 Como melhorar seu código atual (e futuro) utilizando funções Lambda. Paulo Silveira | [email protected] Bacharel e mestre em computação pela Universidade de São Paulo. Fundador do GUJ.com.br, trabalha com Java há 11 anos. É um dos responsáveis técnicos pelos cursos da Caelum. Raphael Lacerda | [email protected] Pós-graduado em Engenharia de Sistemas. Atua como analista de sistemas no Banco do Brasil e ministra cursos na Caelum Bra- sília. Entusiasta por expressividade de código e DSLs. Possui as certificações SCJP e SCWCD. É um dos responsáveis técnicos pelos cursos da Caelum.

description

Lambda from Java 8

Transcript of 55_Lambda

Page 1: 55_Lambda

37 \

_lambda

Você sabe ordenar uma lista? Sabe selecionar os elementos de uma lista a partir de um critério? E extrair os valores de uma determina-da propriedade do objeto de uma lista? São tarefas comuns que estamos cansados de repeti-las. Mas será que conhecemos a melhor forma de escrevê-las? Há como fazer de forma mais concisa, sem perder a legibilidade?Neste artigo vamos mostrar o que muda nessas tarefas do dia a dia ao utilizar bibliotecas como o Google Guava e LambdaJ, que adi-cionam um sabor funcional ao Java atual. Depois chegaremos ao futuro Java 8, para ver como o lambda e os defender methods estão mudando a linguagem em direção ao funcional.

Chegando ao

Lambda no Java 8

Como melhorar seu código atual (e futuro) utilizando funções Lambda.

Paulo Silveira | [email protected] Bacharel e mestre em computação pela Universidade de São Paulo. Fundador do GUJ.com.br, trabalha com Java há 11 anos. É um

dos responsáveis técnicos pelos cursos da Caelum.

Raphael Lacerda | [email protected] Pós-graduado em Engenharia de Sistemas. Atua como analista de sistemas no Banco do Brasil e ministra cursos na Caelum Bra-

sília. Entusiasta por expressividade de código e DSLs. Possui as certificações SCJP e SCWCD. É um dos responsáveis técnicos pelos cursos da Caelum.

Page 2: 55_Lambda

/ 38

Programação funcional é um tema em alta mesmo no mercado corporativo. Sua ascensão ficou bem

apresentada pelo artigo de Steve Vinosky, “Welcome to the functional web”, e pode ser claramente vis-ta pela grande quantidade de linguagens funcionais (ou ao menos com um pouco mais de características funcionais) na JVM. Scala e Clojure são expoentes aqui. Os artigos na MundoJ revelam também essa tendência.

Java é orientada a objetos. O que poderíamos aproveitar do conceito do paradigma funcional para melhorar alguns pontos subjetivos do nosso código: legibilidade, expressividade e concisão? Usando ape-nas a API padrão, muito pouco. Ficamos reféns das longas e “verborrágicas” classes anônimas, ou de la-ços que se repetem exaustivamente.

Como o Java e o JCP estão reagindo a essa ten-dência? Certamente a linguagem está bastante de-fasada, não só em relação às outras com pequena penetração no mercado corporativo, como Scala e Clojure, mas também do Ruby e Python, sem contar o C#, que já possui recursos funcionais muito avan-çados há bastante tempo.

Para a oitava edição da plataforma, prevista para setembro de 2013, teremos a inclusão de uma sin-taxe própria para definir lambdas, em estilo muito similar a essas linguagens. Veremos, neste artigo, como será essa nova sintaxe, junto com algumas no-vidades da JSR 335.

Mas precisamos esperar ainda um ano para tirar proveito de uma API mais elaborada, além da sintaxe adocicada?

Ao final deste artigo você conhecerá duas biblio-tecas funcionais: Guava e LambdaJ. Elas possuem uma robusta API para facilitar o trabalho do dia a dia, em especial relacionado a coleções. O LambdaJ vai além: abusa das proxies dinâmicas para mimeti-zar uma sintaxe diferente.

Você pode ler este artigo de maneira relativa-mente independente: mostraremos cada uma das abordagens para resolver problemas parecidos, en-volvendo simples manipulações de coleções, utili-zando a classe Palestrante. A Listagem 1 mostra essa classe, que implementa Comparable de forma trivial e possui, como atributos, o número de posts do pa-lestrante no GUJ, um id e um nome.

Listagem 1. Implementação de Palestra e Palestran-te.

public class Palestrante implements Comparable<Palestrante> { private final int id; private final String name; private final int postsNoGuj; private boolean favoritado;

public void favoritar() { favoritado = true; } @Override public int compareTo(Palestrante o) { Objects.requireNonNull(o); return Integer.compare(this.id, o.getId()); }}

Algumas tarefas do dia a dia com o Java sem esteróides

Vamos atacar os problemas triviais sem utilizar nenhuma biblioteca de fora do Java. Se temos uma lista de Palestrante chamada palestrantes, como costumamos imprimir todos seus nomes? Escreve-mos um foreach:

for (Palestrante p : palestrantes) { System.out.println(p);}

Para somar todos seus posts, temos outro sim-ples laço:

int soma = 0;for (Palestrante p : palestrantes) { soma += p.getPostsNoGuj();}

Para filtrar todos os que já fizeram mais de 500 posts no GUJ, e depois favoritá-los, o código também é bastante simples:

for (Palestrante p : palestrantes) { if (p.getPostsNoGuj() > 500) p.favoritar();}

Para orderná-los através de posts, criamos um Comparator. Podemos fazer isso em outra classe, mas é comum ficar numa classe anônima:

Comparator<Palestrante> comparador = new Comparator<Palestrante>() { public int compare(Palestrante o1, Palestrante o2) { if (o1.getPostsNoGuj() < o2.getPostsNoGuj()) return -1; if (o1.getPostsNoGuj() > o2.getPostsNoGuj()) return 1; return 0; }};Collections.sort(palestrantes, comparador);

São quatro curtos códigos que estamos cansados de escrever no dia a dia. Como eles ficam adicionan-do um pouco de programação funcional? Será que torná-los curtos facilitaria a legibilidade? Melhora-ria a forma de pensar?

Page 3: 55_Lambda

39 \

Google GuavaO Guava é um apanhado geral de funcionalidades

que os desenvolvedores do Google usam nos projetos Java da empresa. A biblioteca abrange várias áreas como coleções (inclusive criando outros tipos de col-lections como o MultiSet), concorrência, I/O, reflec-tion, validação, dentre outros. Eles resolveram juntar todos esses utilitários em um projeto só, dando ori-gem ao Guava. Está disponível para quem faz geren-ciamento de dependências com o Maven, Gradle, Ivy e Buildr e tem uma boa documentação.

A própria biblioteca diz que para tentar atingir uma programação funcional utilizando Java 7 é só através de um código estranho e muito verboso, ba-sicamente utilizando classes anônimas, portanto ela traz funcionalidades para reverter esse quadro.

O projeto contém algumas classes e interfaces que ajudam na programação no estilo funcional como Function, Predicate, FluentIterable e uma classe uti-litária Collections2. Em suma, podemos fazer uma operação básica como filtragem com praticamente uma combinação de todas elas, o que muda é que, por exemplo, a classe FluentIterable provê essa funciona-lidade seguindo o padrão FluentInterface.

Como primeiro exemplo, a partir de uma lista de participantes, deve-se obter uma lista dos nomes em maiúsculo. Para isso vamos utilizar os métodos da classe FluentIterable from e trasform.

System.out.println(FluentIterable.from(palestrantes).transform(new Function<Palestrante, String>() { @Override public String apply(Palestrante palestrante) { return palestrante.getName().toUpperCase(); }}));

Agora vamos para um problema mais comum. A partir de uma lista de palestrantes, obter somente aqueles que tiveram mais do que 500 posts.

System.out.println(FluentIterable.from(palestrantes).filter( new Predicate<Palestrante>() { @Override public boolean apply(Palestrante palestrante) { return palestrante.getPostsNoGuj() > 500; }}));

Extraindo métodos e utilizando imports estáti-cos, conseguimos um código mais sucinto:

System.out.println(from(palestrantes).filter( comPostsMaiorQue500()));

Para fazer funções de ordenação, vamos usar a classe Ordering, que é um comparador fluente e pode ser usado para manipular, estender e fazer uso de

Comparators. Ela possui alguns métodos utilitários para ordenação, como levar em conta valores null, ordem reversa, ordem lexicográfica, verificar se a lista está ordenada, dentre outros. Vamos fazer três exem-plos rápidos de ordenação. Primeiramente ordenar uma lista desordenada de participantes pela sua or-dem natural (definida pela interface Comparable).

List<Palestrantes> palestrantesOrdenadosPorId = Ordering.natural().sortedCopy(palestrantesDesordenados);

Depois vamos ordenar por nome, para isso vamos criar utilizar a classe Function.

Function<Palestrante, String> ordernacaoPorNome = new Function<Palestrante, String>() { @Override public String apply(Palestrante p) { return p.getName(); }};List<Palestrante> palestrantes =Ordering.natural(). onResultOf(ordernacaoPorNome). sortedCopy(palestrantes);

Por fim ordená-los por nome e posts no guj, onde nomeComparator e postsComparator representam referências para classes anônimas que implementam a interface Comparator.

List<Palestrante> palestrantesNomePosts = Ordering.from(nomeComparator).compound( postsComparator).sortedCopy(palestrantes);

Concluindo, a principal vantagem do Guava em relação à API nativa do Java é que ele possui alguns métodos de suporte mais efetivos, entretanto criar classes anônimas Function e Predicate não muda muito em quantidade/expressividade de código.

LambdaJLambdaJ é uma bibioteca para manipular cole-

ções de uma forma mais simples e natural. Foi criada por Mario Fusco e surgiu devido à necessidade de en-tender melhor uma parte do domínio que lidava com interações em coleções em um projeto que ele parti-cipava. A biblioteca foi desenhada como sendo uma DSL interna para o Java. Segundo Fusco, esse código era complexo, repetitivo e de difícil leitura. Os desen-volvedores gastavam mais tempo tentando adivinhar o que um determinado loop fazia do que escrevendo--o. E ele afirma: “...códigos como este são feitos para o computador ler e não o programador...”. Bom, a si-tuação parece familiar para você?

Ela é muito fácil de se utilizar, tem uma boa do-cumentação e basta ir ao site do projeto para baixá--la, inclusive já possui um jar único com todas as de-pendências e está disponível também para quem faz o gerenciamento com o Maven. Na parte técnica, ela faz muito uso de proxy e reflexão, o que a torna mais

Page 4: 55_Lambda

/ 40

expressiva que as anteriores, todavia um pouco me-nos eficiente com relação ao desempenho. Recomen-da-se verificar na página do projeto a sua análise de desempenho e a questão toda pode se resumir a um trade-off, perdendo um pouco no desempenho para ganhar na expressividade de código. Sua principal classe é a Lambda, que contém uma série de métodos (funções) estáticos.

Inicialmente podemos imprimir o nome de todos os participantes, para isso vamos utilizar a função joinFrom.

System.out.println(joinFrom(palestrantes).getName());

O import estático do método joinFrom foi feito para facilitar a leitura. Agora vamos ordenar os par-ticipantes a partir da quantidade de posts, para isso vamos utilizar o método sort.

List<Palestrante> participantesOrdenadosPorPost = sort(palestrantes, on(Palestrante.class). getPostsNoGuj());

O item de comparação é obtido a partir do méto-do on. Podemos obter uma expressividade melhor ao extrair a comparação para um método privado.

List<Palestrante> participantesOrdenadosPorPost = sort(palestrantes, porPostsNoGuj());

A classe Lambda possui método de agregação como avg, max e min. Exemplo:

int totalDePosts = sumFrom(palestrantes). getPostsNoGuj();

Agora a partir de uma lista de participantes, va-mos colocar todos os nomes em maiúsculo. Primeiro vamos extrair o nome dos participantes. Para isso, será usado o método extract.

List<String> nomesDosPalestrantes = extract(palestrantes, on(Palestrante.class). getName());

Com o nome dos participantes, o objetivo agora é colocá-los em letra maiúscula. Para isso vamos usar o método convert e a interface do LambdaJ Converter. Ela especifica como converter um objeto de um tipo em outro. No exemplo será de String para String.

List<String> nomesMaiusculos = convert( nomeDosPalestrantes, new Converter<String, String>(){ @Override public String convert(String nome){ return nome.toUpperCase(); }});

Podemos fazer um pequeno refactoring para tor-ná-lo mais legível:

List<String> nomesMaiusculos = convert(nomeDosPalestrantes, paraMaiusculo());

Temos agora o seguinte problema, mais comum no dia a dia do desenvolvedor. A partir de uma lista de palestrantes, selecionar os palestrantes com mais de 500 posts e colocá-los como favoritos. Já sabemos como é essa solução usando Java puro, ocupando al-gumas linhas de código. Já com LambdaJ tudo se re-solve com apenas uma linha. Para isso vamos utilizar o método select para selecionar os participantes e o método forEach para percorrer essa lista e favoritá--los. Também iremos usar o método having e grea-terThanOrEqualTo, ambos do Hamcrest, uma depen-dência do LambdaJ.

forEach(select(palestrantes,having(on( Palestrante.class).getPostsNoGuj(), greaterThanOrEqualTo(500)))).favoritar();

Poderia ter sido usado o método and e or para adicionar outras restrições. Agora a leitura ficou fá-cil, todavia ainda pode ser melhorada, tornar-se mais expressiva. Vamos extrair a parte de comparação para um método privado e parametrizar o valor a ser com-parado.

forEach(select(palestrantes, comPostsMaiorQue(500))).favoritar();

O LambdaJ também possui uma classe Lambda-Collection que segue o padrão Fluent Interface assim como o FluentIterable do Guava. Vamos utilizá-la no seguinte problema: tendo uma lista de palestras (considere a nova classe Palestra abaixo), selecionar as palestras que tiveram uma votação superior a 100, então a partir desta selecionar os seus palestrantes ordenados por quantidade de posts. Para isso vamos utilizar os métodos with, que devolve uma referência para uma LambdaCollection, retain, que tem funcio-namento análogo ao select e o extract que já vimos previamente:

public class Palestra { private final String titulo; private final Palestrante palestrante; private final int quantidadeDeVotos; // getters e constructor omitidos } List<Palestrante> palestrantes = with(palestras).

retain(having(on(Palestra.class). getQuantidadeDeVotos(), greaterThanOrEqualTo(100))). extract(on(Palestra.class).getPalestrante()). sort(on(Palestrante.class).getPostsNoGuj());

Page 5: 55_Lambda

41 \

Novamente, com uma refatoração, temos:

List<Palestrante> palestrantes = with(palestras). retain(comQuantidadeDeVotosMaiorQue(100)). extract(palestrante()).sort(porPostsNoGuj());

Por fim, recomendamos olhar nas referências para verificar as outras funcionalidades da biblioteca, alguns métodos como index, group e project podem resolver problemas de uma forma mais concisa do que a sua atual solução. Por exemplo, em um cenário de aplicações distribuídas, em que há a necessidade de se serializar objetos para transferi-los entre JVMs diferentes, o padrão DTO pode ser utilizado. Então podemos chegar ao seguinte código, caso queiramos instanciar objetos do tipo DadosPessoais que tam-bém possuam o atributo nome:

List<DadosPessoais> palestrantesParaTransferencia = project(palestrantes,DadosPessoais. class,on(Palestrante.class). getId(),on(Palestrante.class).getName());

Lambda no Java 8Apesar de estar planejado apenas para setembro

de 2013, você já pode utilizar milestones do JDK8, disponíveis para os principais sistemas operacionais, inclusive para o Mac OSX. O time do lambda do JDK 8 é liderado por Brian Goetz, muito conhecido por seu livro de programação concorrente na plataforma Java.

Direto ao código. Dada uma List<Palestrante> palestrantes, como imprimir todos eles?

palestrantes.forEach(new Block<Palestrante>() { public void apply(Palestrante p) { System.out.println(p); } });

Quem conhece um pouco da API de coleções sabe que não há um método forEach dentro de List, nem em suas principais superinterfaces: Collection e Ite-rable. Para esse código funcionar, além dessa interfa-ce Block precisar existir, esse método forEach precisa

ter sido adicionado. E no Java 8 ele foi, dentro da in-terface Iterable.

Isso é bastante perigoso: evoluir uma interface adicionando novos métodos quebram classes exis-tentes que a implementavam! Como o time fez isso, minimizando os riscos? Eles adicionaram suporte aos extension methods. Se você olhar o código-fonte da interface Iterable, encontrará o seguinte método:

void forEach(Block<? super T> block) default { Iterables.forEach(this, block); }

Agora você pode criar métodos em interfaces no Java e colocar uma implementação default, deso-brigando suas implementadoras de o reescreverem. Algo parecido com os mixins do Ruby e com os traits do Scala, mas ainda sem a possibilidade de conter atributos não-estáticos. A palavra-chave default, dentro de um método de interface, é quem faz essa mágica e define-o como extension method. Classes que implementam Iterable não precisarão reescrever esse método.

Há muitas interfaces e classes novas no Java 8 nos pacotes lang e util. Iterables, Comparators, MapStre-am, BiVal/BiValue são apenas algumas delas, além do pacote java.util.functions, onde a Block se encontra. Trabalharemos com elas no nosso dia a dia e vamos utilizar algumas delas nessa seção.

palestrantes.forEach(p -> { System.out.println(p); });

Apesar de trazer muitas novidades, um lambda não pode ser criado de qualquer maneira. O código abaixo não compila:

Object o = p -> { System.out.println(p); };

Uma expressão lambda precisa sempre ser atri-buída/inferida para uma interface/class abstrata que possui apenas um único método abstrato (antiga-mente chamadas de SAM: single abstract method). A especificação, ainda em andamento, as chamam agora de functional interfaces. Por exemplo, para um Runnable, conseguimos inferir um lambda que não

> Na edição número 52 da MundoJ, Bruno Kioshita fez uma excelente introdução sobre paradigma funcional, explicando conceitos

como Functions, Predicates, dentre outros. Também abordou como fazer o uso da biblioteca Apache Functor, que possui ideias

parecidas com as bibliotecas que serão descritas neste artigo. Por isso, iremos focar essencialmente na prática de como utilizar funções

em Java, atualmente com bibliotecas externas e futuramente com o Lambda no Java 8.

> Já na edição 53, Leandro Moreira fez um artigo de introdução à linguagem Clojure, remetendo a alguns conceitos de Programação

Funcional. Nesta mesma edição Hugo Ferreira descreve vários problemas que podem ser resolvidos com programação Objeto-Funcional

e, por fim, Rafael Ferreira traz o recurso de pattern matching da linguagem funcional Scala.

mais programação funcional na MundoJ/

Page 6: 55_Lambda

/ 42

recebe argumentos:

Runnable r = () -> { System.out.println(); };

Como o compilador sabe que esse conteúdo vai para dentro do método run()? Pois é o único método abstrato da interface. Assim como o método apply(T o) é o único da interface Block<T>.

Podemos ir mais adiante. Quando o lambda vai realizar apenas uma única invocação de método com todos os parâmetros recebidos, podemos criá-lo atra-vés de uma referência para um método:

palestrantes.forEach(System.out::println);

Assustador? O compilador vai inferir que o Block a ser passado para o forEach vai ser uma invocação do método println em cima de System.out, passando o único parâmetro que esse Block pode receber: um palestrante. Se você tivesse passado uma referência para um método que recebe mais de um parâmetro, o compilador não conseguiria inferir o lambda!

Vale lembrar que isso não é um “method lite-ral”, da mesma forma que temos class literals (como String.class, por exemplo). Fazer Method m = System.out::println, ou algo semelhante, não compila. Uma referência a um método nada mais é que outra for-ma de escrever um lambda, então possui as mesmas restrições: há necessidade de uma interface funcional envolvida na expressão.

Assim como o forEach, há muitos novos exten-sions methods na interface Iterable, conhecidos dos programadores funcionais: map, reduce, filter, grou-pBy, mapped etc. Para pegar o número de posts que cada Palestrante tem no GUJ, fazemos:

Iterable<Integer> posts = palestrantes.map( p -> p.getPostsNoGuj());

Nesse caso nem precisamos usar as chaves depois dos parâmetros. Não precisamos utilizá-los quando o conteúdo do método é uma instrução de return. O mesmo ocorre com os parênteses dos parâmetros, que são opcionais no caso de ser apenas um. Em ou-tras palavras, poderíamos escrever:

Iterable<Integer> posts = palestrantes.map((p) -> { return p.getPostsNoGuj(); } );

Ou ainda podemos usar a notação de method re-ference:

Iterable<Integer> posts = palestrantes.map(Palestrante::getPostsNoGuj);

Dado que temos os inteiros, podemos somá-los com o reduce (similar ao foldLeft ou inject em outras linguagens):

Integer total = posts.reduce(0, (total, proximo) -> total+proximo);

O reduce recebe o valor inicial da conta, para de-pois aplicar, item a item, o lambda dado. Esse lambda possui dois parâmetros e será inferido a uma imple-mentação da nova interface BinaryOperator.

E para filtrar quem tem mais de 500 posts no GUJ? Passamos um lambda para ser utilizado como implementação do método test da nova interface Predicate:

palestrantes.filter(p -> p.getPostsNoGuj() > 500);

Se você quer invocar o método favoritar em cada um desses palestrantes, basta utilizar o forEach que já conhecemos:

palestrantes.filter(p -> p.getPostsNoGuj() > 500). forEach(Palestrante::favoritar);

Quer finalmente ordená-los? Finalmente há o método sort na interface list!

palestrantes.sort((p1, p2) -> …. )

Passando seu Comparator como argumento, po-dendo ser inferido por um lambda.

Com esses novos recursos, o código Java se apro-xima ao de linguagens como Scala e Ruby. O mesmo código em Java, Scala e Ruby, sem abusar muito de outros recursos da linguagem (como o underscore do Scala), ficaria:

palestrantes.map(Palestrante::getPostsNoGuj). reduce(0, (n, x) -> n+x);palestrantes.map(_.postsNoGuj).fold(0)(n,x => n+x)palestrantes.map(&:postsNoGuj).inject(0){|n,x| n+x}

Esse foi apenas um sucinto começo do que está por vir. Vale conhecer todos os métodos dentro de Iterable, assim como as interfaces do java.util.func-tions e as novas superinterfaces das collections. Há ainda references para construtores, novos métodos em classes importantes do Java 8 e pequenas melho-rias por toda API. Será um grande passo para a pla-

> Existe também o já conhecido projeto Apache Collections, que possui algumas novas interfaces e classes utilitárias para manipular

coleções.

/ mais projetos: Apache Collections

Page 7: 55_Lambda

43 \

> “Herança e Composição – os princípios por trás dos

padrões”, ed. 39 da MundoJ – Eduardo Guerra

> “JPA 2: Os novos recursos inspirados no Hibernate”, ed.

39 da MundoJ – Paulo Silveira e Raphael Lacerda

> “Enums desmistificadas”, ed. 26 da MundoJ – Alexandre

Gazola

> Série “Design patterns para um Mundo Real”, eds. 21, 22

e 23 da MundoJ – Rodrigo Yoshima

para saber mais/

taforma. Ao mesmo tempo, alguns outros itens ain-da ficaram de fora, como a sintaxe simplificada para criação de coleções e literais para membros da classe.

Considerações finaisUtilizar o Guava e o LambdaJ pode trazer diversos

ganhos a sua aplicação. Mas será que o código é mais expressivo? Possui mais abstração? É mais conciso? São critérios de difícil definição e há bastante dis-cussão a respeito. Deixamos links na referência sobre esse assunto.

Mesmo que seu código esteja agora mais expres-sivo, será que essas novas bibliotecas não serão uma barreira grande para novos programadores da equi-pe? É certamente um ponto que deve ser considerado ao adotar APIs como essas. Assim como o impacto de performance que o LambdaJ pode trazer por causa do uso de muitas dynamic proxies, esses são trade-offs que devem ser estudados.

E quando começar a utilizar o Java 8? Apesar de já haver milestones sólidos, a API está mudando bas-tante, além de que não há IDE nenhuma com suporte a nova sintaxe. É provável que, no início do ano de 2013, tanto Eclipse quanto Netbeans ofereçam su-porte.

Para baixar os builds do JDK8:

> http://openjdk.java.net/projects/jdk8/

> http://openjdk.java.net/projects/lambda/

Para ver a evolução do lambda no JDK8, conheça sua

antiga sintaxe e propostas:

> http://blog.caelum.com.br/trabalhando-com-closures-

no-java-8/

> http://www.javac.info/

Para conhecer mais do LambdaJ:

> http://blog.caelum.com.br/codigo-expressivo-e-

programacao-funcional-em-java-com-lambdaj

> http://code.google.com/p/lambdaj/wiki/LambdajFeatures

DSLs, interfaces fluentes e outros patterns envolvidos aqui:

> http://martinfowler.com/dsl.html

> http://martinfowler.com/bliki/FluentInterface.html

> http://blog.jayway.com/2012/02/07/builder-pattern-

with-a-twist/

Conhecendo mais do Guava:

> http://code.google.com/p/guava-libraries/

Expressividade, abstração e concisão:

> http://www.joelonsoftware.com/items/2006/08/01.html

> http://gafter.blogspot.com.br/2007/03/on-expressive-

power-of-programming.html

Um pouco de teoria sobre o cálculo lambda e programação

funcional:

> http://steve.vinoski.net/pdf/IC-Welcome_to_the_

Functional_Web.pdf

> http://blog.caelum.com.br/comecando-com-o-calculo-

lambda-e-a-programacao-funcional-de-verdade/

/referências

Geraldo Ferraz | [email protected] desenvolvedor da Cast e ministra cursos na Caelum Brasília.

No projeto em que trabalho, chegamos no ponto em que melhorar legibilidade e expressividade tor-nou-se uma prioridade. Por muito tempo o projeto permaneceu com muitos loops e estruturas de condi-ções encadeadas, e por mais que extraíssemos métodos não conseguíamos ler o código e saber de primei-ra o que estava sendo feito. Com o LambdaJ conseguimos melhorar todos os aspectos citados, entretanto, adicionamos bastante complexidade e alta dependência da API. Com alguma refatoração é possível dei-xar o código de forma que a complexidade fique encapsulada tornando o uso muito mais intuitivo.

/eu uso