Java 8! Ordenando dados com Stream

Neste tutorial vou apresentar um novo recursos do Java 8, o qual tem o objetivo de ordenação de dados a partir de uma lista. A algum tempo, postei o tutorial Java 8! Filtrando dados com Stream, neste veremos então como ordenar dados com o uso de Stream e expressões Lambdas. Para isto, vou criar uma classe chamada Person e gerar uma lista de dados a partir dela e esta lista será ordenada com o uso do recursos Stream do Java 8.

No exemplo a seguir temos a classe Person, a qual será formada por três atributos, name, age e salary, conforme a Listagem 1.

  • Listagem 1 – Classe Person
public class Person {
    private String name;
    private Integer age;
    private Double salary;

    public Person(String name, int age, Double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }

    public Double getSalary() {
        return salary;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }
}

Na classe Main – Listagem 2 – vamos criar uma lista do tipo Person e atribuir a cada posição desta lista valores nos atributos via método construtor. No método testSortOne(), recebemos a lista como parâmetro e usamos o método sort() da classe java.util.Collections para criar o sistema de ordenação pelo atributo name de forma ascendente [a – z]. Para este recursos utilizo uma classe anônima.

  • Listagem 2 – Classe Main
package com.mballem.tutorial;

import java.util.ArrayList;
import java.util.List;
import java.util.Collections;

public class Main {

    public static void main(String[] args) {

        List<Person> persons = new ArrayList<>();

        persons.add(new Person("Ana Maria", 25, 3200.50));
        persons.add(new Person("Bianca", 35, 3440.50));
        persons.add(new Person("Marta", 28, 5500.00));
        persons.add(new Person("Breno", 22, 3330.70));
        persons.add(new Person("Mario", 34, 2200.50));
        persons.add(new Person("Ricardo", 55, 3200.00));
        persons.add(new Person("Pietra", 26, 3400.50));
        persons.add(new Person("Fabiana", 44, 4200.60));
        persons.add(new Person("Airton", 29, 1500.50));

        testSortOne(persons);     
    }

    private static void testSortOne(List<Person> persons) {		
	      //Usando classe anonima
	      Collections.sort(persons, new Comparator<Person>() {		
		        public int compare(Person p1, Person p2) {
			          return p1.getName().compareTo(p2.getName());
		        }
	      });

	      for (Person person : persons) {		
		        System.out.println(person.toString());
	      }
    }
}

Em seguida, o próximo passo é realizar um loop na lista e imprimir o resultado no console por meio de um System.out.println(). Então, como resultado, teremos no console a seguinte saída:

Person{name='Airton', age=29, salary=1500.5}
Person{name='Ana Maria', age=25, salary=3200.5}
Person{name='Bianca', age=35, salary=3440.5}
Person{name='Breno', age=22, salary=3330.7}
Person{name='Fabiana', age=44, salary=4200.6}
Person{name='Mario', age=34, salary=2200.5}
Person{name='Marta', age=28, salary=5500.0}
Person{name='Pietra', age=26, salary=3400.5}
Person{name='Ricardo', age=55, salary=3200.0}

Analisando a saída no console do método testSortOne(), veja que os objetos foram ordenados pelo nome, bem como a instrução passada na classe anônima. Porém, o Java 8 fornece um recurso que torna mais simples esta operação, onde você não precisa criar uma classe anônima para adicionar a regra de ordenação e nem executar o loop em uma instrução separada. Vejo como fazer isto usando o recurso de Stream com Lambda no método testSortTwo() da Listagem 3.

  • Listagem 3 – Método testSortTwo
private static void testSortTwo(List<Person> persons) {
    persons.stream()
           .sorted((p1, p2) -> p1.getName().compareTo(p2.getName()))
           .forEach(p -> System.out.println(p));
}

O método testSortTwo(), assim como o método testSortOne(), recebe como parâmetro uma lista contendo os objetos do tipo Person. No entanto, desta vez, usamos o próprio objeto da lista para realizar todas as operações necessárias: ordenação e impressão no console.

A interface java.util.Collection, que é a superclasse de java.util.List, fornece o método stream(), e este, provê o método sorted() que a partir de uma expressão lambda recebe a instrução referente a ordenação pelo atributo name.

Em seguida, o método usado é o foreach(), que por meio de outras expressão lambda vai exibir o resultado no console. Enfim, a operação está encerrada, agora compare as instruções usadas nos métodos testSortOne() e testSortTwo() para ver as diferenças e como no segundo método o processo se tornou mais simples e menor.

Caso você queira mudar a ordem de ordenação, basta mudar a ordem dos parâmetros na expressão lambda do método sorted():

.sorted((p1, p2) -> p2.getName().compareTo(p1.getName()))

E a saída no console para esta operação seria a seguinte:

Person{name='Airton', age=29, salary=1500.5}
Person{name='Ana Maria', age=25, salary=3200.5}
Person{name='Bianca', age=35, salary=3440.5}
Person{name='Breno', age=22, salary=3330.7}
Person{name='Fabiana', age=44, salary=4200.6}
Person{name='Mario', age=34, salary=2200.5}
Person{name='Marta', age=28, salary=5500.0}
Person{name='Pietra', age=26, salary=3400.5}
Person{name='Ricardo', age=55, salary=3200.0}

Suponha que você deseja realizar a ordenação da lista pelo atributo age de forma ascendente [0 – 9]. Veja na Listagem 4 como proceder:

  • Listagem 4 – Método testSortThree
private static void testSortThree(List<Person> persons) {
    persons.stream()
           .sorted((p1, p2) -> p1.getAge().compareTo(p2.getAge()))
           .forEach(p -> System.out.println(p));
}

Saída no console:

Person{name='Breno', age=22, salary=3330.7}
Person{name='Ana Maria', age=25, salary=3200.5}
Person{name='Pietra', age=26, salary=3400.5}
Person{name='Marta', age=28, salary=5500.0}
Person{name='Airton', age=29, salary=1500.5}
Person{name='Mario', age=34, salary=2200.5}
Person{name='Bianca', age=35, salary=3440.5}
Person{name='Fabiana', age=44, salary=4200.6}
Person{name='Ricardo', age=55, salary=3200.0}

Agora, caso você queira o retorno apenas com as idades e de forma ordenada, construa uma operação como a da Listagem 5.

  • Listagem 5 – Método testSortFour
private static void testSortFour(List<Person> persons) {
    persons.stream()
        .mapToInt((p) -> p.getAge())
        .sorted()
        .forEach((p) -> System.out.printf("[%s]", p));
}

E o resultado seria o seguinte:

[22][25][26][28][29][34][35][44][55]

No método testSortFour() foi incluído na operação o método mapToInt(). Este método recebe como parâmetro uma expressão lambda que retorna para o processo o atributo que você deseja obter como resultado, substituindo assim, todo o objeto Person pelo atributo age. Então, age é ordenado por sorted() de forma natural, que seria o mesmo que de [0 – 9]. Por fim, usamos o foreach() para imprimir no console o resultado obtido.

Referencia – https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

Curso JasperReports & JasperSoft Studio
Curso JasperReports & JasperSoft Studio

Ballem

Marcio Ballem é bacharel em Sistemas de Informação pelo Centro Universitário Franciscano em Santa Maria/RS. Tem experiência com desenvolvimento Delphi e Java em projetos para gestão pública e acadêmica. Possui certificação em Java, OCJP 6.

Você pode gostar...