As expressões lambda têm outra utilidade além de salvar linhas de código?
Existem recursos especiais fornecidos pelas lambdas que resolveram problemas que não eram fáceis de resolver? O uso típico que eu vi é que, em vez de escrever isso:
Comparator<Developer> byName = new Comparator<Developer>() {
@Override
public int compare(Developer o1, Developer o2) {
return o1.getName().compareTo(o2.getName());
}
};
Podemos usar uma expressão lambda para reduzir o código:
Comparator<Developer> byName =
(Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName());
(o1, o2) -> o1.getName().compareTo(o2.getName())
Comparator.comparing(Developer::getName)
Respostas:
As expressões Lambda não alteram o conjunto de problemas que você pode resolver com Java em geral, mas definitivamente facilitam a solução de certos problemas, apenas pelo mesmo motivo de não estarmos mais programando em linguagem assembly. A remoção de tarefas redundantes do trabalho do programador facilita a vida e permite fazer coisas que você nem tocaria de outra maneira, apenas pela quantidade de código que você precisaria produzir (manualmente).
Mas expressões lambda não estão apenas salvando linhas de código. Expressões lambda permitem definir funções , algo para o qual você poderia usar classes internas anônimas como uma solução alternativa antes, é por isso que você pode substituir classes internas anônimas nesses casos, mas não em geral.
Mais notavelmente, expressões lambda são definidas independentemente da interface funcional para a qual serão convertidas, portanto, não há membros herdados aos quais eles possam acessar; além disso, eles não podem acessar a instância do tipo que implementa a interface funcional. Dentro de uma expressão lambda
this
esuper
com o mesmo significado que no contexto circundante, consulte também esta resposta . Além disso, você não pode criar novas variáveis locais que sombream variáveis locais do contexto circundante. Para a tarefa pretendida de definir uma função, isso remove muitas fontes de erro, mas também implica que, para outros casos de uso, pode haver classes internas anônimas que não podem ser convertidas em uma expressão lambda, mesmo se estiver implementando uma interface funcional.Além disso, a construção
new Type() { … }
garante produzir uma nova instância distinta (comonew
sempre). Instâncias anônimas de classe interna sempre mantêm uma referência a sua instância externa, se criadas em um nãostatic
contexto. Por outro lado, as expressões lambda capturam apenas uma referênciathis
quando necessário, ou seja, se elas acessamthis
ou não sãostatic
membros. E eles produzem instâncias de uma identidade intencionalmente não especificada, o que permite que a implementação decida em tempo de execução se deve reutilizar instâncias existentes (consulte também “ Uma expressão lambda cria um objeto no heap toda vez que é executado? ”).Essas diferenças se aplicam ao seu exemplo. Sua construção anônima de classe interna sempre produzirá uma nova instância, também poderá capturar uma referência à instância externa, enquanto sua
(Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName())
é uma expressão lambda não capturadora que será avaliada para um singleton em implementações típicas. Além disso, ele não produz um.class
arquivo no seu disco rígido.Dadas as diferenças em termos de semântica e desempenho, as expressões lambda podem mudar a maneira como os programadores resolverão certos problemas no futuro, é claro, também devido às novas APIs que abraçam idéias de programação funcional utilizando os novos recursos da linguagem. Consulte também expressão lambda do Java 8 e valores de primeira classe .
fonte
Linguagens de programação não são para máquinas executadas.
Eles são para os programadores pensarem .
Os idiomas são uma conversa com um compilador para transformar nossos pensamentos em algo que uma máquina pode executar. Uma das principais queixas sobre Java de pessoas que vêm para ele de outras línguas (ou deixam -lo para outros idiomas) costumavam ser que obriga um determinado modelo mental sobre o programador (ou seja, tudo é uma classe).
Não vou avaliar se isso é bom ou ruim: tudo é trade-offs. Mas o Java 8 lambdas permite que os programadores pensem em termos de funções , algo que você não poderia fazer anteriormente em Java.
É a mesma coisa que um programador de procedimentos que aprende a pensar em termos de classes quando se trata de Java: você os vê gradualmente passar de classes que são estruturas glorificadas e ter classes 'auxiliares' com vários métodos estáticos e passar para algo que assemelha-se mais a um design racional de OO (mea culpa).
Se você pensar nelas como uma maneira mais curta de expressar classes internas anônimas, provavelmente não as achará muito impressionantes da mesma maneira que o programador de procedimentos acima provavelmente não achou que as classes fossem um grande aprimoramento.
fonte
Salvar linhas de código pode ser visto como um novo recurso, se permitir que você escreva um pedaço substancial de lógica de maneira mais curta e clara, o que leva menos tempo para que outras pessoas leiam e entendam.
Sem expressões lambda (e / ou referências de método), os
Stream
pipelines seriam muito menos legíveis.Pense, por exemplo, como
Stream
seria o pipeline a seguir se você substituísse cada expressão lambda por uma instância de classe anônima.Seria:
É muito mais difícil escrever do que a versão com expressões lambda e é muito mais suscetível a erros. Também é mais difícil de entender.
E este é um pipeline relativamente curto.
Para tornar isso legível sem expressões lambda e referências a métodos, você teria que definir variáveis que contêm as várias instâncias de interface funcional que estão sendo usadas aqui, o que teria dividido a lógica do pipeline, dificultando a compreensão.
fonte
Comparator
for,sorted
pois ele se compara em ordem natural de qualquer maneira. Talvez altere para comparar o comprimento das strings ou similar, para tornar o exemplo ainda melhor?compareToIgnoreCase
para fazer com que ele se comportasse diferente desorted()
.compareToIgnoreCase
ainda é um mau exemplo, pois você pode simplesmente usar oString.CASE_INSENSITIVE_ORDER
comparador existente . A sugestão de @ tobias_k de comparar por comprimento (ou qualquer outra propriedade que não possua um comparador embutido) se encaixa melhor. A julgar pelos exemplos de código de perguntas e respostas SO, as lambdas causaram muitas implementações desnecessárias de comparadores ...Iteração interna
Ao iterar o Java Collections, a maioria dos desenvolvedores costuma obter um elemento e depois processá- lo. Ou seja, retire esse item e, em seguida, use-o ou reinsira-o etc. Com as versões pré-8 do Java, você pode implementar uma classe interna e fazer algo como:
Agora, com o Java 8, você pode fazer melhor e menos detalhado com:
ou melhor
Comportamentos como argumentos
Adivinhe o seguinte caso:
Com a interface do Java 8 Predicate, você pode fazer melhor assim:
Chamando assim:
Fonte: DZone - Por que precisamos de expressões lambda em Java
fonte
numbers.forEach((Integer value) -> System.out.println(value));
a expressão lambda é composta de duas partes, a da esquerda do símbolo de seta (->), listando seus parâmetros e a da direita, contendo o corpo . O compilador descobre automaticamente que a expressão lambda tem a mesma assinatura do único método não implementado da interface Consumer.Existem muitos benefícios em usar lambdas em vez da classe interna a seguir:
Torne o código mais compacto e expressivo sem introduzir mais semânticas de sintaxe de idioma. você já deu um exemplo em sua pergunta.
Ao usar lambdas, você pode programar com operações de estilo funcional em fluxos de elementos, como transformações de redução de mapa em coleções. veja java.util.function & java.util.stream pacotes de documentação.
Não há arquivo de classes físicas gerado para lambdas pelo compilador. Assim, diminui os aplicativos entregues. Como Memory atribui a lambda?
O compilador otimizará a criação de lambda se o lambda não acessar variáveis fora de seu escopo, o que significa que a instância lambda será criada apenas uma vez pela JVM. para obter mais detalhes, você pode ver a resposta de @ Holger à pergunta A referência de método ao cache é uma boa idéia no Java 8? .
O Lambdas pode implementar interfaces com vários marcadores além da interface funcional, mas as classes internas anônimas não podem implementar mais interfaces, por exemplo:
fonte
Lambdas são apenas açúcar sintático para classes anônimas.
Antes das lambdas, classes anônimas podem ser usadas para obter a mesma coisa. Toda expressão lambda pode ser convertida em uma classe anônima.
Se você estiver usando o IntelliJ IDEA, ele poderá fazer a conversão:
fonte
Para responder sua pergunta, o fato é que as lambdas não permitem que você faça nada que não pudesse fazer antes do java-8; ao contrário, permite escrever um código mais conciso . Os benefícios disso são que seu código será mais claro e flexível.
fonte
Uma coisa que ainda não vi mencionada é que um lambda permite definir a funcionalidade onde é usado .
Portanto, se você tem alguma função de seleção simples, não precisa colocá-la em um local separado com um monte de clichê, basta escrever um lambda que seja conciso e relevante localmente.
fonte
Sim, existem muitas vantagens.
fonte