-
O estilo funcional introduzido no Java 8 nos ajuda a reduzir a lacuna entre a lógica de negócios e o código. Isso nos permite contar a história em um fluxo natural em um nível superior. Em vez de dizer como deseja fazer, você pode dizer o que deseja fazer.
-
O código fica mais limpo e conciso.
-
Funções de alta ordem nos permitem:
- Enviar funções para outras funções
- Crie funções dentro de outras funções
- Retornar funções de outras funções
Esta é uma grande vitória para Java, onde precisamos enviar, criar e retornar objetos para fazer isso. Seremos capazes de escrever código mais confiável, focado e mais fácil de reutilizar.
-
Graças aos lambdas, podemos fazer cálculos preguiçosos. Quando uma expressão lambda é enviada como argumento de método, o compilador a avaliará quando for chamada no método. Isso é diferente dos argumentos normais do método, que são avaliados imediatamente.
-
Lambdas tornam a escrita de testes unitários divertida. Eles nos permitem criar testes leves, limpos, de tamanho pequeno e rápidos de escrever. Podemos erradicar o código em teste usando lambdas. Isso nos permite testar como todos os tipos de cenários afetarão o código.
-
Novos padrões para aprender.
-
E muito mais!
break
, mudam drasticamente o comportamento do loop, forçando-nos a entender não apenas o que o código está tentando alcançar, continue
mas return
também a entender como o loop funciona. Agora veremos como podemos transformar loops em códigos mais concisos e legíveis.
Deixe a codificação começar!
Trabalharemos com artigos. Um artigo possui título, autor e diversas tags.
private class Article {
private final String title;
private final String author;
private final List<String> tags;
private Article(String title, String author, List<String> tags) {
this.title = title;
this.author = author;
this.tags = tags;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public List<String> getTags() {
return tags;
}
}
Cada exemplo conterá uma solução tradicional usando loops e uma solução usando os novos recursos do Java 8. No primeiro exemplo, queremos encontrar o primeiro artigo da coleção com a tag “Java”. Vamos dar uma olhada em uma solução usando um loop.
public Article getFirstJavaArticle() {
for (Article article : articles) {
if (article.getTags().contains("Java")) {
return article;
}
}
return null;
}
Agora vamos resolver o problema usando operações da API Stream.
public Optional<Article> getFirstJavaArticle() {
return articles.stream()
.filter(article -> article.getTags().contains("Java"))
.findFirst();
}
Muito legal, não é? Primeiro usamos a operação filter
para encontrar todos os artigos com a tag “Java” e depois usamos findFirst()
para obter a primeira ocorrência. Como os fluxos são preguiçosos e o filtro retorna um fluxo, essa abordagem processará apenas os elementos até encontrar a primeira correspondência. Agora vamos colocar todos os artigos marcados como “Java” em vez de apenas o primeiro. Primeiro a solução usando loops.
public List<Article> getAllJavaArticles() {
List<Article> result = new ArrayList<>();
for (Article article : articles) {
if (article.getTags().contains("Java")) {
result.add(article);
}
}
return result;
}
Solução usando operações de fluxo.
public List<Article> getAllJavaArticles() {
return articles.stream()
.filter(article -> article.getTags().contains("Java"))
.collect(Collectors.toList());
}
Neste exemplo, usamos uma operação collect
para encurtar o fluxo resultante, em vez de declarar uma coleção e adicionar explicitamente as entradas correspondentes. Até agora tudo bem. É hora de exemplos que farão a API Stream realmente brilhar. Vamos agrupar todos os artigos por autor. Como de costume, começamos resolvendo-o usando loops:
public Map<String, List<Article>> groupByAuthor() {
Map<String, List<Article>> result = new HashMap<>();
for (Article article : articles) {
if (result.containsKey(article.getAuthor())) {
result.get(article.getAuthor()).add(article);
} else {
ArrayList<Article> articles = new ArrayList<>();
articles.add(article);
result.put(article.getAuthor(), articles);
}
}
return result;
}
Podemos encontrar uma solução limpa para este problema usando operações de fluxo?
public Map<String, List<Article>> groupByAuthor() {
return articles.stream()
.collect(Collectors.groupingBy(Article::getAuthor));
}
Incrível! Ao usar uma operação groupingBy
e uma referência de método getAuthor()
, obtemos um código limpo e legível. Agora vamos encontrar o restante das tags usadas na coleção. Vamos começar com um exemplo de loop:
public Set<String> getDistinctTags() {
Set<String> result = new HashSet<>();
for (Article article : articles) {
result.addAll(article.getTags());
}
return result;
}
Ok, vamos dar uma olhada em como podemos resolver isso usando operações de stream:
public Set<String> getDistinctTags() {
return articles.stream()
.flatMap(article -> article.getTags().stream())
.collect(Collectors.toSet());
}
Legal! flatmap
nos ajuda a nivelar a lista de tags em um único fluxo de resultados, que então usamos collect
para criar o conjunto de retorno.
GO TO FULL VERSION