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 PersonComparator – Listagem 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 Main – Listagem 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
- Interface Comparable – http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html
- Interface Comparator – http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html

