Atualizado: 21/09/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Ordenação de Dados com a Stream API em Java

Embora as coleções, que frequentemente servem como fonte para os streams, já possuam seus próprios métodos de ordenação, a Stream API também oferece essa funcionalidade diretamente no fluxo de dados. Essa capacidade é especialmente útil dentro de um pipeline de operações, permitindo que os dados sejam ordenados após uma filtragem ou mapeamento, antes de uma operação terminal.

Ordenação Natural com sorted()

Para uma ordenação simples em ordem ascendente (ou "natural"), é utilizado o método sorted().

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

public class Program {
    public static void main(String[] args) {
        List<String> phones = new ArrayList<>();
        Collections.addAll(phones, "iPhone 15", "Pixel 8", "Galaxy S24",
                "Xiaomi 14", "OnePlus 12", "Xperia 1 V");

        phones.stream()
                .filter(p -> p.length() < 10)
                .sorted() // Ordenação em ordem alfabética natural
                .forEach(s -> System.out.println(s));
    }
}

Este método funciona bem para tipos que já possuem uma ordem definida, como números e strings. No entanto, ele depende da implementação da interface Comparable pela classe dos elementos do stream.

Pixel 8
Xiaomi 14
iPhone 15

Ordenação Customizada com sorted(Comparator)

Quando a ordenação natural não é suficiente ou quando os objetos não implementam Comparable, é necessário fornecer uma lógica de ordenação customizada. Isso é feito através do método sorted(Comparator), que aceita um Comparator como argumento.

Vamos considerar a seguinte classe Phone:

class Phone {
    private String name;
    private String company;
    private int price;

    // Construtor e Getters...
    public Phone(String name, String comp, int price) {
        this.name = name;
        this.company = comp;
        this.price = price;
     }
    public String getName() { return name; }
    public String getCompany() { return company; }
    public int getPrice() { return price; }
}

Existem três abordagens principais para fornecer um Comparator.

1. Classe Separada (Abordagem Tradicional)

É possível criar uma classe que implementa Comparator. Esta abordagem é verbosa e raramente usada em código moderno, mas é útil para entender o conceito.

class PhoneComparatorByName implements Comparator<Phone> {
    @Override
    public int compare(Phone a, Phone b) {
        return a.getName().compareToIgnoreCase(b.getName());
    }
}
// Uso: phoneStream.sorted(new PhoneComparatorByName())

2. Expressão Lambda (Abordagem Concisa)

Uma expressão lambda permite definir a lógica de comparação diretamente onde ela é necessária, tornando o código mais compacto.

// Ordenando por nome
phoneStream.sorted((p1, p2) -> p1.getName().compareToIgnoreCase(p2.getName()));

// Ordenando por preço
phoneStream.sorted((p1, p2) -> Integer.compare(p1.getPrice(), p2.getPrice()));

3. Métodos de Fábrica Comparator (Abordagem Recomendada)

A forma mais moderna, legível e segura é usar os métodos estáticos da interface Comparator, como comparing, comparingInt, etc., combinados com referências de método.

// Ordenando por nome (case-insensitive)
phoneStream.sorted(Comparator.comparing(Phone::getName, String.CASE_INSENSITIVE_ORDER));

// Ordenando por preço (ordem crescente)
phoneStream.sorted(Comparator.comparingInt(Phone::getPrice));

Esta abordagem é preferível por ser mais declarativa: ela diz "o quê" comparar, em vez de "como" comparar.

Ordenação por Múltiplos Critérios

Um cenário muito comum é a necessidade de ordenar por um segundo critério quando o primeiro resulta em empate. Isso é facilmente alcançado encadeando comparadores com o método thenComparing.

Por exemplo, para ordenar os telefones por preço e, em caso de preços iguais, desempatar pelo nome em ordem alfabética:

Comparator<Phone> comparator = Comparator.comparingInt(Phone::getPrice)
                                         .thenComparing(Phone::getName);

phoneStream.sorted(comparator);

Exemplo Completo e Prático

O código abaixo demonstra a ordenação por múltiplos critérios em um exemplo executável.

import java.util.Comparator;
import java.util.stream.Stream;

class Phone {
    private String name;
    private String company;
    private int price;

    public Phone(String name, String comp, int price) {
        this.name = name;
        this.company = comp;
        this.price = price;
    }

    public String getName() { return name; }
    public String getCompany() { return company; }
    public int getPrice() { return price; }
}

public class SortingExample {
    public static void main(String[] args) {
        Stream.of(
            new Phone("iPhone 15", "Apple", 999),
            new Phone("Pixel 8", "Google", 799),
            new Phone("iPhone 14", "Apple", 799), // Mesmo preço do Pixel 8
            new Phone("Galaxy S24", "Samsung", 899),
            new Phone("Xiaomi 14", "Xiaomi", 699)
        )
        // Ordena primeiro por preço (crescente), depois por nome (alfabético)
        .sorted(Comparator.comparingInt(Phone::getPrice)
                          .thenComparing(Phone::getName))
        .forEach(p -> System.out.printf("%s (%s) - %d USD\n",
                p.getName(), p.getCompany(), p.getPrice()));
    }
}

O resultado será:

Xiaomi 14 (Xiaomi) - 699 USD
iPhone 14 (Apple) - 799 USD
Pixel 8 (Google) - 799 USD
Galaxy S24 (Samsung) - 899 USD
iPhone 15 (Apple) - 999 USD

Note que o iPhone 14 e o Pixel 8, ambos com o mesmo preço, foram desempatados alfabeticamente pelo nome.

Resumo

  • O método sorted() ordena elementos em sua ordem natural (requer Comparable).
  • O método sorted(Comparator) permite uma ordenação customizada.
  • A forma moderna e recomendada de criar um Comparator é com os métodos de fábrica Comparator.comparing() ou comparingInt(), utilizando referências de método (ex: Phone::getPrice).
  • Para ordenar por múltiplos critérios, encadeie comparadores com o método thenComparing.
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com