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