Comparar Objectos com o Comparator

Tal como vimos no post anterior, ao implementarmos o interface Comparable, estamos a definir uma forma de comparar instâncias da classe
(no exemplo dado, o objectivo era criar uma lista de objectos Person ordenados por ordem de idades).
No entanto eu posso querer ter a flexibilidade de poder comparar objectos usando mais do que um critério (por exemplo, para uns
casos eu quero comparar idades mas noutros eu quero comparar os primeiros nomes). Resumindo, para criar objectos comparaveis
de duas formas diferentes, preciso de dois comparadores.

Procedimento:

criar um class que implementa o interface java.util.Comparator. Este interface tem um método:
compare com a seguinte assinatura:

	public int compare(Object o1, Object o2)

e retorna zero se o1 e o2 forem iguais, um inteiro negativo se o1
for menor do que o2 e um inteiro positivo se o1 for maior do que o2.

Tal como no método compareTo do interface Comparable, somos nós que decidimos qual
o critério que faz com que um objecto seja maior, igual ou menor do que o outro.

Continuando o exemplo do outro post, temos a class Person
que implementa o interface Comparable:

public class Person implements Comparable {
	private String firstName;

	private String lastName;

	private int age;

	public String getFirstName() {
		return firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public int getAge() {
		return age;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int compareTo(Object anotherPerson)
	throws ClassCastException {
	  if (!(anotherPerson instanceof Person))
	    throw new ClassCastException
               ("Objecto do tipo Person esperado!");
	    int anotherPersonAge = ((Person) anotherPerson).getAge();
	    return this.age - anotherPersonAge;
	  }
}

Até aqui nada de novo. Agora vou criar uma nova classe que implementa o interface Comparator
de forma a poder comparar objectos pelo último nome:

import java.util.Comparator;

public class LastNameComparator implements Comparator {

  public int compare(Object person, Object anotherPerson) {
    String lastName1 =
      ((Person)person).getLastName().toUpperCase();
    String lastName2 =
      ((Person)anotherPerson).getLastName().toUpperCase();
    return lastName1.compareTo(lastName2);

  }
}

e o mesmo para comparar o primeiro nome:

import java.util.Comparator;

public class FirstNameComparator implements Comparator {
  public int compare(Object person, Object anotherPerson) {
    String firstName1 =
      ((Person)person).getFirstName().toUpperCase();
    String firstName2 =
      ((Person)anotherPerson).getFirstName().toUpperCase();
  return firstName1.compareTo(firstName2);
  }
}

Vamos carregar um array com objectos do tipo
Person
e ordenar de diferentes formas:

public static void main(String[] args) {
	Person[] persons = new Person[3];
	persons[0] = new Person();
	persons[0].setFirstName("Marcus");
	persons[0].setLastName("Miller");
	persons[0].setAge(43);

	persons[1] = new Person();
	persons[1].setFirstName("Stanley");
	persons[1].setLastName("Clark");
	persons[1].setAge(35);

	persons[2] = new Person();
	persons[2].setFirstName("Jaco");
	persons[2].setLastName("Pastorious");
	persons[2].setAge(38);
	//Antes
	System.out.println("--Ordem natural");
	for(int i = 0; i  Ordenado por idade");
	for(int i = 0; i  Ordenado por primeiro nome");
	for(int i = 0; i  Ordenado por �ltimo nome");
	for(int i = 0; i < persons.length; i++){
		System.out.println(persons[i].getFirstName()
                   + ", " + persons[i].getLastName() + "," +
                persons[i].getAge());
	}
}

e o resultado é o esperado:

e o resultado é o esperado:
--Ordem natural
Marcus, Miller,43
Stanley, Clark,35
Jaco, Pastorious,38
--> Ordenado por idade
Stanley, Clark,35
Jaco, Pastorious,38
Marcus, Miller,43
--> Ordenado por primeiro nome
Jaco, Pastorious,38
Marcus, Miller,43
Stanley, Clark,35
--> Ordenado por �ltimo nome
Stanley, Clark,35
Marcus, Miller,43
Jaco, Pastorious,38

Se não quiser criar várias classes para os comparadores,
posso fazê-las inner classes da classe Person

public class Person implements Comparable{
	private String firstName;
	private String lastName;
	private int age;

	public String getFirstName() {
		return firstName;
	}
	public String getLastName() {
		return lastName;
	}
	public int getAge() {
		return age;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int compareTo(Object anotherPerson)
                              throws ClassCastException{
	  if(!(anotherPerson instanceof Person))
	    throw new ClassCastException
                   ("Objecto do tipo Person esperado!");
	    int anotherPersonAge = ((Person)anotherPerson).getAge();
	    return this.age - anotherPersonAge;
	}

	public static Comparator LastNameComparator =
               new Comparator(){
  	public int compare(Object person, Object anotherPerson) {
	  String lastName1 =
                 ((Person)person).getLastName().toUpperCase();
	 String lastName2 =
                ((Person)anotherPerson).getLastName().toUpperCase();
  	return lastName1.compareTo(lastName2);
	 }
	}
	public static Comparator FirstNameComparator =
              new Comparator(){
  	public int compare(Object person, Object anotherPerson) {
	  String firstName1 =
                ((Person)person).getFirstName().toUpperCase();
	  String firstName2 =
                 ((Person)anotherPerson).getFirstName().toUpperCase();
  	return firstName1.compareTo(lastName2);
             }
          }
}

o que torna o código mais fácil de manter!

Deixar uma Resposta