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.
package com.mballem.tutorial; /** * Created by Ballem on 22/07/2015. */ public class Person { private String name; private int 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 int 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.
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) { Listpersons = 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 persons) { //Usando classe anonima Collections.sort(persons, new Comparator () { 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.
private static void testSortTwo(Listpersons) { 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 próximo método usado é o foreach()
, que por meio de outras expressão lambda vai exibir o resultado no console. Pronto, 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='Ricardo', age=55, salary=3200.0} Person{name='Pietra', age=26, salary=3400.5} Person{name='Marta', age=28, salary=5500.0} Person{name='Mario', age=34, salary=2200.5} Person{name='Fabiana', age=44, salary=4200.6} Person{name='Breno', age=22, salary=3330.7} Person{name='Bianca', age=35, salary=3440.5} Person{name='Ana Maria', age=25, salary=3200.5} Person{name='Airton', age=29, salary=1500.5}
Suponha agora que você deseja agora realizar a ordenação da lista pelo atributo age
de forma ascendente [0 – 9]. Veja na Listagem 4 como proceder:
private static void testSortThree(Listpersons) { 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='Mario', age=25, salary=2200.5} Person{name='Fabiana', age=25, salary=4200.6} Person{name='Marta', age=26, salary=3400.5} Person{name='Marta', age=28, salary=5500.0} Person{name='Airton', age=29, salary=1500.5} Person{name='Bianca', age=35, salary=3440.5} Person{name='Ricardo', age=55, salary=3200.0}
Agora, caso você queira que o retorno seja apenas as idades e de forma ordenada, construa uma operação como a da Listagem 5.
private static void testSortFour(Listpersons) { 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