Ordenando coleções com Comparable & Comparator

Com certeza em algum momento você já se deparou com a necessidade de ordenar algum tipo de lista ou mesmo um array, e teve duvidas de como fazer isso. O Java fornece a classe java.util.Collections e seu método sort(), que são capazes de ordenar uma lista e a classe java.util.Arrays.sort() para ordenação de arrays. Porém, para fazer uso deste recurso é necessário ainda informar os critérios que serão usados na ordenação.

Existem duas interfaces para configurar estes critérios, a interface java.lang.Comparable e a interface java.util.Comparator. Vamos agora criar uma classe chamada Person Listagem 1 – a qual contem dois atributos: name (String) e age (int).

package com.mballem.tutorial;

/**
 * Created by IntelliJ IDEA.
 * User: Marcio Ballem
 * Date: 29/07/13
 * Time: 14:47
 * https://www.mballem.com/
 */
public class Person implements Comparable {

    private String name;

    private int age;

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

    String getName() {
        return name;
    }

    int getAge() {
        return age;
    }

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

Agora, vamos usar a classe Main para realizar alguns testes. No método main() existe uma lista, chamada persons, a qual na execução do código ira ser impressa no console pelo método printer().

package com.mballem.tutorial;

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

/**
 * Created by IntelliJ IDEA.
 * User: Marcio Ballem
 * Date: 29/07/13
 * Time: 14:52
 * https://www.mballem.com/
 */
public class Main {

    public static void main(String[] args) {
        List persons = new ArrayList();
        persons.add(new Person("Carla Maria", 20));
        persons.add(new Person("Diogo Flores", 22));
        persons.add(new Person("Marta Rios", 32));
        persons.add(new Person("Julia Peres", 25));
        persons.add(new Person("Aline Pereira", 23));
        persons.add(new Person("Bianca Jasmim", 19));

        Main.printer(persons);
    }

    private static void printer(List persons) {
        System.out.println(persons.toString());
    }
}

O resultado do método printer() terá como saída o resultado abaixo. Note que como não usamos nenhum tipo de ordenação, a lista foi impressa exatamente na mesma ordem em que seus elementos foram adicionados no método main().

[
Person{name='Carla Maria', age=20}, 
Person{name='Diogo Flores', age=22}, 
Person{name='Marta Rios', age=32}, 
Person{name='Julia Peres', age=25}, 
Person{name='Aline Pereira', age=23}, 
Person{name='Bianca Jasmim', age=19}
]

Vamos fazer agora uma ordenação por idade, ou seja, pelo atributo age. Desta forma, quando a lista for novamente impressa no console, os elementos devem estar ordenados em ordem crescente (0 – 9). Primeiro devemos fazer duas alterações na classe Person. Observe na Listagem 3 que adicionamos a assinatura da classe Person a interface java.lang.Comparable. Por adicionar esta interface, devemos implementar o seu método compareTo(). Será neste método que vamos definir a ordenação por idade.

public class Person implements Comparable {    

    //códigos anteriores omitidos.

    public int compareTo(Person person) {
        if (this.age < person.age) {
            return -1;
        }
        if (this.age > person.age) {
            return 1;
        }
        return 0;
    }
}

O método compareTo() tem como retorno um int com as seguintes características:

  • Valor negativo, se this.object < parâmetro;
  • Valor positivo, se this.object > parâmetro;
  • Valor zero, se this.object for igual ao parâmetro.

O retorno deste método é que vai classificar se o objeto atual da lista ou de um array é menor, maior ou igual ao objeto anterior, e assim, a classificação é realizada. Retornando a classe Main, adicione uma chamada a um novo método da classe chamado sortByAge(), descrito na Listagem 4.

public class Main {

    public static void main(String[] args) {
        List persons = new ArrayList();
        persons.add(new Person("Carla Maria", 20));
        persons.add(new Person("Diogo Flores", 22));
        persons.add(new Person("Marta Rios", 32));
        persons.add(new Person("Julia Peres", 25));
        persons.add(new Person("Aline Pereira", 23));
        persons.add(new Person("Bianca Jasmim", 19));

        Main.sortByAge(persons);
    }  

    private static void sortByAge(List persons) {
        Collections.sort(persons);
        System.out.println(persons.toString());
    }
}

Neste método adicionamos persons como parâmetro no método sort() da classe Collections e em seguida, a lista será impressa no console. O método sort() usará o método compareTo() da classe Persons para realizar a ordenação. Veja o que será impresso no console desta vez, e repare que a ordenação foi realizada em ordem crescente de idade.

[
Person{name='Bianca Jasmim', age=19}, 
Person{name='Carla Maria', age=20}, 
Person{name='Diogo Flores', age=22}, 
Person{name='Aline Pereira', age=23}, 
Person{name='Julia Peres', age=25}, 
Person{name='Marta Rios', age=32}
]

O passo seguinte será criar uma ordenação por nome, usando o atributo name. Para realizar a ordenação por nome, vamos criar uma classe chamada PersonComparatorListagem 5 – e implementar a interface Comparator. A interface requer a implementação do método compare(). Este método recebe dois parâmetros, os quais serão utilizados para a comparação entre os atributos name da lista.

package com.mballem.tutorial;

import java.util.Comparator;

/**
 * Created by IntelliJ IDEA.
 * User: Marcio Ballem
 * Date: 29/07/13
 * Time: 15:11
 * https://www.mballem.com/
 */
public class PersonComparator implements Comparator {

    public int compare(Person p1, Person p2) {
        return p1.getName().compareTo(p2.getName());
    }
}

Na classe MainListagem 6 – vamos adicionar o método sortByName() para visualizar o resultado. Note, que desta vez, o método Collections.sort() recebeu um segundo parâmetro, que nada mais é que uma instancia da classe PersonComparator.

package com.mballem.tutorial;

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

/**
 * Created by IntelliJ IDEA.
 * User: Marcio Ballem
 * Date: 29/07/13
 * Time: 14:52
 * https://www.mballem.com/
 */
public class Main {

    public static void main(String[] args) {
        List persons = new ArrayList();
        persons.add(new Person("Carla Maria", 20));
        persons.add(new Person("Diogo Flores", 22));
        persons.add(new Person("Marta Rios", 32));
        persons.add(new Person("Julia Peres", 25));
        persons.add(new Person("Aline Pereira", 23));
        persons.add(new Person("Bianca Jasmim", 19));

        Main.sortByName(persons);
    }

    private static void sortByName(List persons) {
        Collections.sort(persons, new PersonComparator());
        System.out.println(persons.toString());
    }
}

Como saída no console teremos o resultado abaixo. Observe que desta vez a ordenação ocorreu de forma alfabética de a – z.

[
Person{name='Aline Pereira', age=23}, 
Person{name='Bianca Jasmim', age=19}, 
Person{name='Carla Maria', age=20}, 
Person{name='Diogo Flores', age=22}, 
Person{name='Julia Peres', age=25}, 
Person{name='Marta Rios', age=32}
]

Como temos também uma ordenação por idade, caso tivéssemos dois ou mais nomes iguais e com idades diferentes, a ordenação seria por nome e por idade na sequência, como mostra o exemplo abaixo:

[
Person{name='Aline Pereira, age='23}, 
Person{name='Bianca Jasmim, age='19}, 
Person{name='Carla Maria, age='20}, 
Person{name='Maria Rios, age='29}, 
Person{name='Maria Rios, age='30}, 
Person{name='Marta Rios, age='32},
Person{name='Zilo Pires, age='21}
]

A classe PersonComparator só foi criada por que já existia em Person uma implementação do método compareTo(). Se fosse necessário order apenas por nome, poderíamos usar o método compareTo() da interface Comparable e o método compareTo() já disponível nos objetos do tipo String. Na Listagem 7 substituímos a implementação por idade pela implementação por nome. Desta forma, na classe Main basta remover do método sortByName() a instancia de PersonComparator que ele ordenará por nome, mas não mais por idade.

package com.mballem.tutorial;

/**
 * Created by IntelliJ IDEA.
 * User: Marcio Ballem
 * Date: 29/07/13
 * Time: 14:47
 * https://www.mballem.com/
 */
public class Person implements Comparable {

    private String name;

    private int age;

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

    String getName() {
        return name;
    }

    int getAge() {
        return age;
    }

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

    /*public int compareTo(Person person) {
        if (this.age < person.age) {
            return -1;
        }
        if (this.age > person.age) {
            return 1;
        }
        return 0;
    }*/

    public int compareTo(Person person) {
        return this.name.compareTo(person.getName());
    }
}

Referencias

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...