<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gabriel Ferreira Mendes</title>
    <description>The latest articles on DEV Community by Gabriel Ferreira Mendes (@gabrielferreira).</description>
    <link>https://dev.to/gabrielferreira</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1237070%2F6cab3888-c7b8-41e2-86d1-46f1f18f4f5e.jpeg</url>
      <title>DEV Community: Gabriel Ferreira Mendes</title>
      <link>https://dev.to/gabrielferreira</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gabrielferreira"/>
    <language>en</language>
    <item>
      <title>Entendendo Java Stream API na prática</title>
      <dc:creator>Gabriel Ferreira Mendes</dc:creator>
      <pubDate>Tue, 09 Jan 2024 13:10:16 +0000</pubDate>
      <link>https://dev.to/gabrielferreira/entendendo-java-stream-api-na-pratica-4f46</link>
      <guid>https://dev.to/gabrielferreira/entendendo-java-stream-api-na-pratica-4f46</guid>
      <description>&lt;p&gt;Se você está aprendendo Java agora, ou vindo de outra linguagem, acredito que esse texto possa te ajudar. A &lt;em&gt;Stream API&lt;/em&gt; do Java é uma ferramenta muito poderosa e inversamente a esse fato, ela é muito simples. &lt;/p&gt;

&lt;p&gt;Com pouquíssimas linhas de código, podemos realizar operações que em outras linguagens precisaríamos de, talvez, o dobro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stream API
&lt;/h2&gt;

&lt;p&gt;A &lt;em&gt;Stream API&lt;/em&gt;, apresentada no Java 8, consiste em uma sequencia/coleção de elementos agregados que suportam operações sequenciais e/ou paralelas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;stream()&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;parallelStream()&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com isso, a ideia é abstrair parte do processo de desenvolvimento que antes seria utilizado para "comportamentos", deixando o controle de fluxo e &lt;em&gt;loop's&lt;/em&gt; para a &lt;em&gt;Stream API&lt;/em&gt;. Similar as &lt;em&gt;Threads&lt;/em&gt;, onde aspectos mais complexos são encapsulados e o desenvolvedor fica responsável apenas pela implementação das regras de negócio.&lt;/p&gt;

&lt;p&gt;Existem variações para suportar/facilitar a manipulação de tipos primitivos como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IntStream()&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LongStream()&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DoubleStream()&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dito isso, a &lt;em&gt;Stream API&lt;/em&gt; oferece dois tipos de operações: Operações intermediárias e Operações terminais.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operações intermediárias
&lt;/h2&gt;

&lt;p&gt;Basicamente, operações intermediárias retornam novas stream's e permitem que o programador continue a concatenar/utilizar novas funções.&lt;/p&gt;

&lt;h3&gt;
  
  
  Filter
&lt;/h3&gt;

&lt;p&gt;A operação &lt;strong&gt;filter()&lt;/strong&gt; é usado para filtrar elementos de uma &lt;em&gt;stream&lt;/em&gt; de acordo com uma condição, um predicado, e retorna uma nova &lt;em&gt;stream&lt;/em&gt; contendo apenas os elementos que satisfazem à condição.&lt;/p&gt;

&lt;p&gt;O código a seguir mostra um exemplo de uso dessa operação. Primeiramente é criada uma lista com alguns objetos do tipo &lt;strong&gt;Usuario&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Usuario {
    private String nome;
    private int idade;
    private String email;
    private String senha;;

    public Usuario(String nome, int idade, String email, String senha) {
        this.email = email;
        this.nome = nome;
        this.idade = idade;
        this.senha = senha;
    }

    @Override
    public String toString() {
        return "Usuario [nome=" + nome + 
                      ", idade=" + idade + 
                      ", email=" + email + 
                      ", senha=" + senha + "]";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    private static List&amp;lt;Usuario&amp;gt; populaUsuarios(){
        return  List.of(new Usuario("Ana", 25, "&amp;lt;EMAIL&amp;gt;", "123456"), 
                        new Usuario("Bruno", 21, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Caio", 23, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Daniel", 26, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Simão", 27, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Pedro", 28, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Maria", 25, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("João", 25, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Marcos", 22, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Paulo", 23, "&amp;lt;EMAIL&amp;gt;", "123456"));                  
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, vamos montar uma nova lista apenas com usuários com 25 anos ou mais:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       public static void main(String[] args) throws Exception {
        var listaUsuarios = populaUsuarios();

        var listaUsuariosComVinteCincoAnos = 
                listaUsuarios
                             .stream()
                             .filter(usuario -&amp;gt; usuario.idade &amp;gt;= 25);

        listaUsuariosComVinteCincoAnos.forEach(System.out::println);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chegando ao resultado:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sjizzf3c8f11ix0wvpp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sjizzf3c8f11ix0wvpp.png" alt="Lista de usuários com mais de 25 anos" width="490" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Map
&lt;/h3&gt;

&lt;p&gt;Em algumas situações nos deparamos com a necessidade de transformarmos/modificarmos os objetes da nossa lista. E ai entra a operação &lt;strong&gt;map()&lt;/strong&gt;, que nos permite realizar essas mudanças sem a necessidade de variáveis intermediárias.&lt;/p&gt;

&lt;p&gt;Usando uma função como argumento que, assim como o predicado na operação &lt;strong&gt;filter()&lt;/strong&gt;, também é uma interface funcional. Tornando cada elemento da &lt;em&gt;Stream&lt;/em&gt; em um parâmetro e retornando o elemento processado como resposta. &lt;/p&gt;

&lt;p&gt;Dito isso, imagine que queremos transformar nossa lista de usuários em uma lista de pessoas, para ocultar algumas informações. Para isso vamos criar uma nova classe: &lt;strong&gt;Pessoa&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Pessoa {
    private String nome;
    private int idade;

    public Pessoa(Usuario usuario) {
        this.nome = usuario.getNome();
        this.idade = usuario.getIdade();
    }

    @Override
    public String toString() {
        return "Pessoa [nome=" + nome + ", idade=" + idade + "]";
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aplicando a operação &lt;strong&gt;map()&lt;/strong&gt;, teremos os seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class App {
    public static void main(String[] args) throws Exception {
        var listaUsuarios = populaUsuarios();

        var listaPessoas = 
               listaUsuarios
                            .stream()
                            .map(usuario -&amp;gt; {return new Pessoa(usuario);});

        listaPessoas.forEach(System.out::println);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chegando ao resultado:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6qp9xcvivv6jz8rhmgj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6qp9xcvivv6jz8rhmgj.png" alt="Lista de usuários convertidos em pessoas" width="248" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lembra que as &lt;em&gt;Streams&lt;/em&gt; possuem abstrações para otimizar a manipulação de tipos primitivos (&lt;strong&gt;IntStream&lt;/strong&gt;, &lt;strong&gt;LongStream&lt;/strong&gt;, &lt;strong&gt;DoubleStream&lt;/strong&gt;) e assim evitar &lt;em&gt;overhead&lt;/em&gt;? Então, vou demonstrar isso com a operação &lt;strong&gt;map()&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Utilizando nossa lista de pessoas, vamos criar uma lista contendo apenas a idade das pessoas que estão na lista "original", para isso é preciso implementar os &lt;strong&gt;getters&lt;/strong&gt; da classe &lt;strong&gt;Pessoa&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Pessoa {
    private String nome;
    private int idade;

    public Pessoa(Usuario usuario) {
        this.nome = usuario.getNome();
        this.idade = usuario.getIdade();
    }

    @Override
    public String toString() {
        return "Pessoa [nome=" + nome + ", idade=" + idade + "]";
    }

    public String getNome() {
        return nome;
    }

    public int getIdade() {
        return idade;
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos montar nossa lista de idades, que por baixo dos panos é uma &lt;em&gt;Stream&amp;lt; int &amp;gt;&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class App {
    public static void main(String[] args) throws Exception {
        var listaUsuarios = populaUsuarios();

        var listaPessoas = 
               listaUsuarios
                            .stream()
                            .map(usuario -&amp;gt; {return new Pessoa(usuario);});

        var listaPessoaIdade =
                       listaPessoas
                      .stream()
                      .mapToInt(Pessoa::getIdade)
                      .boxed()
                      .toList();    

        listaPessoaIdade.forEach(System.out::println); 
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chegando ao resultado:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fny0n5ts25pmtqns5eb7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fny0n5ts25pmtqns5eb7x.png" alt="Lista com a idade das pessoas" width="155" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É importante reduzir o &lt;em&gt;overhead&lt;/em&gt; pois nem existem situações onde será necessário operar sobre &lt;em&gt;Streams&lt;/em&gt; de tamanho indeterminado. Para contextos controlados, talvez não faça tanto sentindo se preocupar com o custo computacional das operações.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sorted
&lt;/h3&gt;

&lt;p&gt;Ordenar elementos em uma coleção é uma tarefa recorrente para todo desenvolvedor. E no Java isso é bastante simples, as &lt;em&gt;Stream API&lt;/em&gt; oferece a operação &lt;strong&gt;sorted()&lt;/strong&gt;. Retornando uma nova &lt;em&gt;stream&lt;/em&gt; contendo os elementos da &lt;em&gt;stream&lt;/em&gt; original ordenados de acordo com o critério fornecido.&lt;/p&gt;

&lt;p&gt;Utilizando o método &lt;strong&gt;comparing()&lt;/strong&gt; da interface &lt;strong&gt;Comparator&lt;/strong&gt;, é fornecida uma &lt;em&gt;Function&lt;/em&gt; como parâmetro e assim obtemos um valor chave que será utilizado na ordenação.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class App {
    public static void main(String[] args) throws Exception {
        var listaUsuarios = populaUsuarios();

        var listaPessoa = listaUsuarios
                .stream()
                .map(usuario -&amp;gt; {
                    return new Pessoa(usuario);
                });

        var listaPessoaOrdenadoPorIdade = listaPessoa
                .stream()
                .sorted(Comparator.comparing(Pessoa::getIdade));       

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

        var listaPessoaOrdenadoPorNome = listaPessoa
                .stream()
                .sorted(Comparator.comparing(Pessoa::getNome));        

        listaPessoaOrdenadoPorNome.forEach(System.out::println);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse caso, a classificação das informações foi feita primeiro por idade:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7mvm8ap2zwzvi6akj31h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7mvm8ap2zwzvi6akj31h.png" alt="Lista de pessoas ordenadas por idade" width="265" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E depois de acordo com o nome da pessoa, utilizando a ordem natural (alfabética) definida na interface &lt;strong&gt;Comparator&lt;/strong&gt; para classificar &lt;strong&gt;Strings&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg14xh7vc9zpe5vncsylu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg14xh7vc9zpe5vncsylu.png" alt="Lista de pessoas ordenadas por nome" width="312" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como pôde ver, através de &lt;em&gt;method reference&lt;/em&gt; conseguirmos usar a referência dos métodos &lt;strong&gt;getIdade()&lt;/strong&gt; e &lt;strong&gt;getNome()&lt;/strong&gt; da classe Pessoa como parâmetro para a operação &lt;strong&gt;Comparator.comparing()&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distinct
&lt;/h3&gt;

&lt;p&gt;A operação &lt;strong&gt;distinct()&lt;/strong&gt; retorna uma &lt;em&gt;stream&lt;/em&gt; contendo apenas elementos que são exclusivos, isto é, que não se repetem, de acordo com a implementação do método &lt;strong&gt;equals()&lt;/strong&gt; e &lt;strong&gt;hashCode()&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Ou seja, é necessário sobrescrever esses métodos dentro na nossa classe &lt;strong&gt;Pessoa&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Pessoa {
    private String nome;
    private int idade;

    public Pessoa(Usuario usuario) {
        this.nome = usuario.getNome();
        this.idade = usuario.getIdade();
    }

    @Override
    public String toString() {
        return "Pessoa [nome=" + nome + ", idade=" + idade + "]";
    }

    public String getNome() {
        return nome;
    }

    public int getIdade() {
        return idade;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((nome == null) ? 0 : nome.hashCode());
        result = prime * result + idade;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;

        if (obj == null)
            return false;

        if (getClass() != obj.getClass())
            return false;

        Pessoa other = (Pessoa) obj;

        if (nome == null) {
            if (other.nome != null)
                return false;
        } else if (!nome.equals(other.nome))
            return false;
        if (idade != other.idade)
            return false;

        return true;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após sobrescrever os métodos &lt;strong&gt;equals()&lt;/strong&gt; e &lt;strong&gt;hashCode()&lt;/strong&gt;, vamos adicionar usuários repetidos a nossa lista e utilizar a operação &lt;strong&gt;distinct()&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    private static List&amp;lt;Usuario&amp;gt; populaUsuarios(){
        return  List.of(new Usuario("Ana", 25, "&amp;lt;EMAIL&amp;gt;", "123456"), 
                        new Usuario("Bruno", 21, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Caio", 23, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Daniel", 26, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Simão", 27, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Pedro", 28, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Maria", 25, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("João", 25, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Marcos", 22, "&amp;lt;EMAIL&amp;gt;", "123456"),
                        new Usuario("Paulo", 23, "&amp;lt;EMAIL&amp;gt;", "123456"),

//Nomes Repetidos
                        new Usuario("Ana", 25, "&amp;lt;EMAIL&amp;gt;", "123456"), 
                        new Usuario("Bruno", 21, "&amp;lt;EMAIL&amp;gt;", "123456"));                  
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class App {
    public static void main(String[] args) throws Exception {
        var listaUsuarios = populaUsuarios(); 

        var listaPessoa = listaUsuarios
                .stream()
                .map(usuario -&amp;gt; {
                    return new Pessoa(usuario);
                })
                .distinct();       

        listaPessoa.forEach(System.out::println);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chegando ao resultado:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3fx1zt0nsssajvnzc7a9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3fx1zt0nsssajvnzc7a9.png" alt="Lista de usuários sem redundâncias" width="253" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Limit
&lt;/h3&gt;

&lt;p&gt;A operação &lt;strong&gt;limit()&lt;/strong&gt; retorna uma nova &lt;em&gt;Stream&lt;/em&gt; com apenas a quantidade de elementos passada por parâmetro. Também é conhecida como curto-circuito pois não precisa processar todos os elementos da &lt;em&gt;Stream&lt;/em&gt; original.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class App {
    public static void main(String[] args) throws Exception {
        var listaUsuarios = populaUsuarios();

        var listaPessoa = listaUsuarios
                .stream()
                .map(usuario -&amp;gt; {
                    return new Pessoa(usuario);
                })
                .limit(3);       

        listaPessoa.forEach(System.out::println);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chegando ao resultado:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdcxgm0gl0eneo7iowov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdcxgm0gl0eneo7iowov.png" alt="Lista de pessoas limitando a 3 resultados" width="218" height="54"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Operações terminais
&lt;/h2&gt;

&lt;p&gt;Enquanto operações terminais retornam objetos e/ou resultados que, diferente das operações intermediárias, não são do tipo &lt;em&gt;Stream&lt;/em&gt;. São consideradas operações terminais as operações:&lt;/p&gt;

&lt;h3&gt;
  
  
  ForEach
&lt;/h3&gt;

&lt;p&gt;Através da operação &lt;strong&gt;forEach()&lt;/strong&gt; é possível realizar um &lt;em&gt;loop&lt;/em&gt; sobre todos os elementos de uma &lt;em&gt;Stream&lt;/em&gt; e executar algum tipo de processamento.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class App {
    public static void main(String[] args) throws Exception {
        var listaUsuarios = populaUsuarios();

        listaUsuarios
                .stream()
                .map(usuario -&amp;gt; {
                    return new Pessoa(usuario);
                })
                .forEach(pessoa -&amp;gt; {
                         System.out.println(pessoa.getNome());
                                   });               
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No exemplo, utilizamos &lt;em&gt;lambda&lt;/em&gt; para invocar o método &lt;strong&gt;getNome()&lt;/strong&gt; do objeto pessoa e passa-lo como parâmetro para a operação &lt;strong&gt;forEach()&lt;/strong&gt;. Desta forma será exibidos apenas os nomes de todas as pessoas presentes na &lt;em&gt;Stream&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Average
&lt;/h3&gt;

&lt;p&gt;Para tipos primitivos, a operação &lt;strong&gt;average()&lt;/strong&gt; permite calcular a média dos valores de uma &lt;em&gt;Stream&lt;/em&gt;. Como exemplo, para calcular a média de idade das pessoas, teremos um código similar ao seguinte:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class App {
    public static void main(String[] args) throws Exception {
        var listaUsuarios = populaUsuarios();

        var listaPessoas = listaUsuarios
                .stream()
                .map(usuario -&amp;gt; {
                    return new Pessoa(usuario);
                });

        var value = listaUsuarios
                                 .stream()
                                 .mapToInt(pessoa -&amp;gt; pessoa.getIdade())
                                 .average()
                                 .getAsDouble();

        System.out.println("A média de idade das pessoas é: " + value);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tendo como resultado:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf3k4ljlir4fncx1he6p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf3k4ljlir4fncx1he6p.png" alt="Média de idade dos usuários presentes na lista" width="346" height="24"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repare que no exemplo acima foi utilizada a operação &lt;strong&gt;getAsDouble()&lt;/strong&gt;, isso ocorre pois a operação &lt;strong&gt;average()&lt;/strong&gt; não retorna um valor numérico mas sim um objeto da classe &lt;strong&gt;java.util.Optional&lt;/strong&gt;. Objetos do tipo &lt;strong&gt;Optinonal&lt;/strong&gt; nos permitem lidar com algumas situações de forma simples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Collect
&lt;/h3&gt;

&lt;p&gt;A operação &lt;strong&gt;collect()&lt;/strong&gt; permite a conversão de uma &lt;em&gt;Stream&lt;/em&gt; em uma &lt;em&gt;Collection&lt;/em&gt;, convertendo para os tipos: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;List&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Map&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ao chamarmos a operação &lt;strong&gt;collect()&lt;/strong&gt;, determinando via argumento qual &lt;em&gt;Collection&lt;/em&gt; será retornada através da classe &lt;strong&gt;Collectors&lt;/strong&gt;. Como por exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Collectors.toList()&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collectors.toMap()&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collectiors.toSet()&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public static void main(String[] args) throws Exception {
        var listaUsuarios = populaUsuarios();

        var listaPessoasList = 
               listaUsuarios
                            .stream()
                            .map(usuario -&amp;gt; {return new Pessoa(usuario);})
                            .collect(Collectors.toList());

        System.out.println("List: ");
        System.out.println(listaPessoasList.toString());
        System.out.println();

        var listaPessoasMap = 
               listaUsuarios
                            .stream()
                            .map(usuario -&amp;gt; {return new Pessoa(usuario);})
                            .collect(Collectors.toMap(Pessoa::getNome, Pessoa::getIdade));

        System.out.println("Map: ");                            
        System.out.println(listaPessoasMap.get("Ana"));
        System.out.println();

        var listaPessoasSet = 
               listaUsuarios
                            .stream()
                            .map(usuario -&amp;gt; {return new Pessoa(usuario);})
                            .collect(Collectors.toSet());

        System.out.println("Set: ");
        System.out.println(listaPessoasSet);
        System.out.println();

    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chegando ao resultado:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rkjq4edqfkyh4lfwvjw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rkjq4edqfkyh4lfwvjw.png" alt="Resultado da conversão para: List, Map e Set" width="800" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Count
&lt;/h3&gt;

&lt;p&gt;A operação &lt;strong&gt;count()&lt;/strong&gt; retorna a quantidade de elementos presentes em uma &lt;em&gt;Stream&lt;/em&gt;. Assim como &lt;strong&gt;average()&lt;/strong&gt;, também é classificado como uma operação de redução (&lt;em&gt;reduction&lt;/em&gt;). &lt;/p&gt;

&lt;p&gt;Por exemplo, se quisermos retornar apenas as pessoas cujo o nome se inicia com a letra 'M':&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public static void main(String[] args) throws Exception {
        var listaUsuarios = populaUsuarios();

        var listaPessoas = 
               listaUsuarios
                            .stream()
                            .map(usuario -&amp;gt; {return new Pessoa(usuario);})
                            .filter(pessoa -&amp;gt; pessoa.getNome().toUpperCase().startsWith("M"))
                            .count();

        System.out.println("Quantidade de pessoas com a letra inicial do nome M: " + listaPessoas);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Teremos como resultado:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8efm8g8jtb691i91xduf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8efm8g8jtb691i91xduf.png" alt="Quantidade de pessoas cujo nome começa com a letra 'M'" width="387" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  AllMatch
&lt;/h3&gt;

&lt;p&gt;A operação &lt;strong&gt;allMatch()&lt;/strong&gt; verifica se todos os elementos de uma &lt;em&gt;Stream&lt;/em&gt; atendem a um critério passado como parâmetro, através de um &lt;em&gt;Predicate&lt;/em&gt;, e retorna um valor booleano.  &lt;/p&gt;

&lt;p&gt;Imagine que queremos saber se todas as pessoas da nossa lista são maiores de idade, com a operação &lt;strong&gt;allMatch()&lt;/strong&gt; teríamos um código similar a este:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public static void main(String[] args) throws Exception {
        var listaUsuarios = populaUsuarios();

        var todasAsPessoasSaoMaioresDeIdade = 
               listaUsuarios
                            .stream()
                            .map(usuario -&amp;gt; {return new Pessoa(usuario);})
                            .allMatch(pessoa -&amp;gt; {return pessoa.getIdade() &amp;gt;= 18;});

        System.out.println(todasAsPessoasSaoMaioresDeIdade);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resultado: true.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collections e Streams
&lt;/h2&gt;

&lt;p&gt;Apesar da semelhança entre &lt;em&gt;Collections&lt;/em&gt; e &lt;em&gt;Streams&lt;/em&gt;, os objetivos são bem diferentes. As &lt;em&gt;Collections&lt;/em&gt; tem como principal objetiva a facilidade e eficiência na gestão de seu elementos, fornecendo meios simples intuitivos de armazenamento e acesso de objetos armazenados. &lt;/p&gt;

&lt;p&gt;Enquanto as Streams, apesar de fornecer meios de acessar e manipular seus elementos, não permite que você os altere diretamente. Tendo como objetivo maior descrever declarativamente sua fonte e as operações computacionais que serão executadas sobre essa fonte.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Se você é um dev mais "cascudo" (veio), esse artigo pode parecer simplório e até defasado, afinal tudo isso foi introduzido ao Java na versão 8. Mas para novos programadores e/ou pessoas que estão chegando agora na linguagem, espero que esse artigo possa ajudar a entender um pouco do poder do Java e da funcionalidades/facilidades que a linguagem nos oferece.&lt;/p&gt;

&lt;p&gt;Um grande abraço e até a próxima!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>java</category>
    </item>
    <item>
      <title>Strategy Pattern e SOLID</title>
      <dc:creator>Gabriel Ferreira Mendes</dc:creator>
      <pubDate>Wed, 20 Dec 2023 12:04:19 +0000</pubDate>
      <link>https://dev.to/gabrielferreira/strategy-pattern-e-solid-bj4</link>
      <guid>https://dev.to/gabrielferreira/strategy-pattern-e-solid-bj4</guid>
      <description>&lt;p&gt;Olá,&lt;/p&gt;

&lt;p&gt;Vamos desmistificar o SOLID e de quebra aprender sobre um padrão de projeto bem legal?&lt;/p&gt;

&lt;p&gt;Com este artigo quero compartilhar com vocês um pouco do que tenho estudado e, com alguma sorte, ajudar vocês no compreendimento do &lt;strong&gt;SOLID&lt;/strong&gt; ou do &lt;strong&gt;Strategy Pattern&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Link do artigo: &lt;a href="https://www.linkedin.com/pulse/strategy-pattern-e-solid-gabriel-ferreira-mendes-qdnyf/"&gt;https://www.linkedin.com/pulse/strategy-pattern-e-solid-gabriel-ferreira-mendes-qdnyf/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>solidprinciples</category>
      <category>java</category>
      <category>designpatterns</category>
    </item>
  </channel>
</rss>
