Difference between revisions of "Classes Internas (Java)/Exercício 01: Interfaces java.lang.Comparable e java.util.Comparator"

From Wiki**3

< Classes Internas (Java)
(Solução)
Line 49: Line 49:
 
= Solução =
 
= Solução =
  
[[category:OOP]]
+
== 1. Tabela comparável ==
[[category:Teaching]]
+
 
 +
Para este caso, é necessário definir a classe Table como implementando Comparable.
  
 
<java5>
 
<java5>
 +
/**
 +
* A table holding a fixed number of integers.
 +
*
 +
* It is possible to verify certain predicates against the table's contents.
 +
*/
 +
public class Table implements Comparable<Table> {
 +
 +
/**
 +
* Space for a fixed number of integers.
 +
*/
 +
int _vector[];
 +
 +
/**
 +
* @param nInts
 +
*            number of integers to store.
 +
*/
 +
public Table(int nInts) {
 +
_vector = new int[nInts];
 +
}
 +
 +
/**
 +
* FIXME: insert checks to ensure position is within range.
 +
*
 +
* @param position
 +
*            position to define
 +
* @return value at position
 +
*/
 +
public int getValue(int position) {
 +
return _vector[position];
 +
}
 +
 +
/**
 +
* FIXME: insert checks to ensure position is within range.
 +
*
 +
* @param position
 +
*            position to define
 +
* @param value
 +
*            value to set
 +
*/
 +
public void setValue(int position, int value) {
 +
_vector[position] = value;
 +
}
 +
 +
/**
 +
* Set all positions to the same value.
 +
*
 +
* @param value
 +
*            value to set
 +
*/
 +
public void setAll(int value) {
 +
for (int position = 0; position < _vector.length; position++)
 +
_vector[position] = value;
 +
}
 +
 +
/**
 +
* @param predicate
 +
*            the predicate to validate.
 +
* @return true, if the predicate is valid for at least one position; false,
 +
*        otherwise.
 +
*/
 +
public boolean contains(SelectionPredicate predicate) {
 +
for (int position = 0; position < _vector.length; position++)
 +
if (predicate.ok(_vector[position]))
 +
return true;
 +
return false;
 +
}
 +
 +
/**
 +
* This method makes it easy to get the sum of all elements. As with the
 +
* predicate, this type of algorithm could also be provided from outside:
 +
* instead of a selector, a collector would have to be provided.
 +
*
 +
* @return sum of all elements.
 +
*/
 +
public int getSum() {
 +
int sum = 0;
 +
for (int i : _vector)
 +
sum += i;
 +
return sum;
 +
}
 +
 +
/**
 +
* @see java.lang.Comparable#compareTo(java.lang.Object)
 +
*/
 +
@Override
 +
public int compareTo(Table other) {
 +
return getSum() - other.getSum();
 +
}
 +
}
 
</java5>
 
</java5>
 +
 +
 +
 +
[[category:OOP]]
 +
[[category:Teaching]]

Revision as of 20:28, 18 October 2009

A interface Comparable<T> exige às classes que a implementam a criação de um método ( T é um tipo)

<java5> int compareTo(T other); </java5>

Este método permite estabelecer uma ordem natural sobre objectos do tipo utilizado para parametrizar a interface. Colecções desses objectos podem então ser ordenadas utilizando métodos pré-definidos (e.g., Collections.sort ou Arrays.sort).

O método compareTo deve retornar um inteiro menor que zero, zero, ou maior que zero, caso um objecto seja "menor", igual ( equals), ou "maior" que outro objecto. Como a referência null não representa nenhum objecto, se passada como argumento, não deverá ser retornado nenhum valor, devendo as implementações lançar NullPointerException. No exemplo seguite, a ordem natural é definida pela idade do gato.

<java5> public class Cat implements Comparable<Cat> {

 private int _age;
 private String _name;
 public Gato(int age, String name) { _age = age; _name = name; }
 public int getAge() { return _age; }
 public String getName() { return _name; }
 public int compareTo(Cat cat) {
   if (cat == null) throw new NullPointerException();
   return _age - cat.getAge();
 }

} </java5>

Recordar que equals deve retornar false quando é passada uma referência null como argumento.

Semelhante ao uso da interface Comparable<T>, mas sem definir uma ordem natural para os objectos de uma classe, a interface Comparator<T> permite criar classes (implementações), cujos objectos representam funções de comparação entre dois objectos da classe utilizada como parâmetro do tipo do comparador. O método exigido pela interface Comparator<T> é:

<java5> int compare(T um, T outro); </java5>

O uso é análogo ao da interface Comparable<T>, mas não compromete uma classe com nenhuma função de comparação especial. Considerando o exemplo do gato, a definição seguinte permitiria, por exemplo, ordenar gatos por nome ( String implementa Comparable<String>, definindo ordem lexicográfica).

<java5> import java.util.Comparator; public class CatNameComparator implements Comparator<Cat> {

 public int compare(Cat cat1, Cat cat2) {
   return cat1.getName().compareTo(cat2.getName());
 }

} </java5>

Recordar que a compatibilidade com equals e a simetria da comparação são como para o caso de compareTo (acima).

Problema

  1. Considere a tabela da Aula Prática 04. Redefina a classe como sendo comparável. Diz-se que uma tabela é menor/igual/maior que outra quando se verificar a relação menor/igual/maior entre as somas dos elementos de cada uma.
  2. Considere ainda o caso da alínea anterior. Defina agora dois comparadores (devem ser implementados como classes internas da tabela) que estabelecem as relações de comparação relativamente (i) aos máximos das tabelas e (ii) ao número de elementos (independentemente dos valores).
  3. Considere agora, em lugar de tabelas de inteiros, que as tabelas contêm gatos (classe definida acima). Altere o código da alínea 2(i) para que funcione com as tabelas de gatos.

Solução

1. Tabela comparável

Para este caso, é necessário definir a classe Table como implementando Comparable.

<java5> /**

* A table holding a fixed number of integers.
* 
* It is possible to verify certain predicates against the table's contents.
*/
public class Table implements Comparable { /** * Space for a fixed number of integers. */ int _vector[]; /** * @param nInts * number of integers to store. */ public Table(int nInts) { _vector = new int[nInts]; } /** * FIXME: insert checks to ensure position is within range. * * @param position * position to define * @return value at position */ public int getValue(int position) { return _vector[position]; } /** * FIXME: insert checks to ensure position is within range. * * @param position * position to define * @param value * value to set */ public void setValue(int position, int value) { _vector[position] = value; } /** * Set all positions to the same value. * * @param value * value to set */ public void setAll(int value) { for (int position = 0; position < _vector.length; position++) _vector[position] = value; } /** * @param predicate * the predicate to validate. * @return true, if the predicate is valid for at least one position; false, * otherwise. */ public boolean contains(SelectionPredicate predicate) { for (int position = 0; position < _vector.length; position++) if (predicate.ok(_vector[position])) return true; return false; } /** * This method makes it easy to get the sum of all elements. As with the * predicate, this type of algorithm could also be provided from outside: * instead of a selector, a collector would have to be provided. * * @return sum of all elements. */ public int getSum() { int sum = 0; for (int i : _vector) sum += i; return sum; } /** * @see java.lang.Comparable#compareTo(java.lang.Object) */ @Override public int compareTo(Table other) { return getSum() - other.getSum(); } } </java5>