Os programadores frequentemente precisam classificar elementos de um banco de dados em uma coleção, array ou mapa. Em Java, podemos implementar qualquer algoritmo de classificação que quisermos com qualquer tipo.

Usando o Comparable interface e compareTo() método, podemos classificar usando ordem alfabética, String comprimento, ordem alfabética reversa ou números. O Comparator interface nos permite fazer o mesmo, mas de uma forma mais flexível.

O que quer que queiramos fazer, só precisamos saber como implementar a lógica de classificação correta para determinada interface e tipo.

Classificando com interfaces Comparable e Comparator do Java

Aqui está o que você aprenderá neste artigo sobre classificação de objetos Java:

  • Classificando com Comparable:
    • Classificando um Java List
    • Como o Java compareTo() funciona
    • Como classificar arrays em Java
    • Classificando um Java Map com TreeMap
    • Classificando um Java Set com TreeSet
    • Como evitar ClassCastExceptions ao classificar
    • Usando Comparable com as principais classes Java
  • Classificando com Comparator:
    • Usando Comparator com classes internas anônimas
    • Usando Comparator com expressões lambda

Classificando com Comparável

Começaremos explicando como classificar usando a interface Comparable do Java. Nós usamos Comparable quando há uma única comparação padrão para o objeto que queremos classificar.

Classificando uma lista Java

Neste primeiro exemplo, implementamos Comparable em um Simpson classe, usando Simpson no tipo genérico:


class Simpson implements Comparable<Simpson> {
    String name;

    Simpson(String name) {
        this.name = name;
    }

    @Override
    public int compareTo(Simpson simpson) {
        return this.name.compareTo(simpson.name);
    }
}

public class SimpsonSorting {

     public static void main(String... sortingWithList) {
        List<SimpsonCharacter> simpsons = new ArrayList<>();
        simpsons.add(new SimpsonCharacter("Homer "));
        simpsons.add(new SimpsonCharacter("Marge "));
        simpsons.add(new SimpsonCharacter("Bart "));
        simpsons.add(new SimpsonCharacter("Lisa "));

        Collections.sort(simpsons);
        simpsons.stream().map(s -> s.name).forEach(System.out::print);

        Collections.reverse(simpsons);
        simpsons.stream().forEach(System.out::print);
    }

}

Observe que substituímos o método compareTo() e passamos outro Simpson objeto. Também substituímos o toString() método, apenas para tornar o exemplo mais fácil de ler.

Como funciona o compareTo() do Java

O compareTo() O método compara um determinado objeto ou a instância atual com um objeto especificado para determinar a ordem dos objetos. Aqui está uma rápida olhada em como compareTo() funciona.

Só podemos usar classes que sejam comparáveis ​​com o sort() método. Se tentarmos passar um Simpson que não implementa Comparablereceberemos um erro de compilação.

O sort() método usa polimorfismo passando qualquer objeto que seja Comparable. Os objetos serão então classificados conforme o esperado.

A saída do código anterior seria:


Bart Homer Lisa Marge 

Se quiséssemos reverter a ordem, poderíamos trocar o sort() para reverse(); de:


Collections.sort(simpsons);

para:


Collections.reverse(simpsons);

Implantando o reverse() método mudaria a saída anterior para:


Marge Lisa Homer Bart 

Como classificar um array Java

Em Java, podemos classificar um array com qualquer tipo que quisermos, desde que implemente o Comparable interface. Aqui está um exemplo:


public class ArraySorting {

    public static void main(String... moeTavern) {
        int() moesPints = new int() {9, 8, 7, 6, 1};

        Arrays.sort(moesPints);

        Arrays.stream(moesPints).forEach(System.out::print);

        Simpson() simpsons = new Simpson(){new Simpson("Lisa"), new Simpson("Homer")};

        Arrays.sort(simpsons);
        Arrays.stream(simpsons).forEach(System.out::println);
    }
}

Em primeiro sort() invocação, a matriz é classificada para:


1 6 7 8 9

No segundo sort() invocação, ele é classificado para:


Homer Lisa

Lembre-se de que os objetos personalizados devem implementar Comparable para ser classificado, mesmo como uma matriz.

Como evitar ClassCastExceptions ao classificar objetos Java

Se o objeto Simpson não estivesse sendo implementado Comparable, uma ClassCastException seria lançada. Se você executar isso como um teste, verá algo como o seguinte resultado:


Error:(16, 20) java: no suitable method found for sort(java.util.List<com.javaworld.javachallengers.sortingcomparable.Simpson>)
    method java.util.Collections.<T>sort(java.util.List<T>) is not applicable
      (inference variable T has incompatible bounds
        equality constraints: com.javaworld.javachallengers.sortingcomparable.Simpson
        lower bounds: java.lang.Comparable<? super T>)
    method java.util.Collections.<T>sort(java.util.List<T>,java.util.Comparator<? super T>) is not applicable
      (cannot infer type-variable(s) T
        (actual and formal argument lists differ in length))

Este log pode ser confuso, mas não se preocupe. Basta ter em mente que um ClassCastException será lançado para qualquer objeto classificado que não implemente o Comparable interface.

Classificando um mapa com TreeMap

A API Java inclui muitas classes para auxiliar na classificação, incluindo TreeMap. No exemplo abaixo, usamos TreeMap para classificar chaves em um Map.


public class TreeMapExample {

    public static void main(String... barney) {
        Map<SimpsonCharacter, String> simpsonsCharacters = new TreeMap<>();
        simpsonsCharacters.put(new SimpsonCharacter("Moe"), "shotgun");
        simpsonsCharacters.put(new SimpsonCharacter("Lenny"), "Carl");
        simpsonsCharacters.put(new SimpsonCharacter("Homer"), "television");
        simpsonsCharacters.put(new SimpsonCharacter("Barney"), "beer");

        System.out.println(simpsonsCharacters);
    }
}

TreeMap usa o compareTo() método implementado pelo Comparable interface. Cada elemento no resultado Map é classificado por sua chave. Neste caso, a saída seria:


Barney=beer, Homer=television, Lenny=Carl, Moe=shotgun

Lembre-se, porém: se o objeto não implementar Comparablevocê receberá um ClassCastException.

Classificando um conjunto com TreeSet

O Set interface é responsável por armazenar valores únicos, mas quando usamos a implementação TreeSet, os elementos inseridos serão ordenados automaticamente à medida que os adicionamos:


public class TreeSetExample {

    public static void main(String... barney) {
        Set<SimpsonCharacter> simpsonsCharacters = new TreeSet<>();
        simpsonsCharacters.add(new SimpsonCharacter("Moe"));
        simpsonsCharacters.add(new SimpsonCharacter("Lenny"));
        simpsonsCharacters.add(new SimpsonCharacter("Homer"));
        simpsonsCharacters.add(new SimpsonCharacter("Barney"));

        System.out.println(simpsonsCharacters);
    }
}

A saída deste código é:


Barney, Homer, Lenny, Moe

Novamente, se usarmos um objeto que não é Comparableobteremos um ClassCastException.