(→Solução) |
(→Solução) |
||
Line 145: | Line 145: | ||
</java5> | </java5> | ||
+ | == 2. Comparadores de Máximo e Comprimento == | ||
+ | Notar que as classes internas são static e que apenas estão contidas na classe Table por conveniência de ocultação de código. | ||
+ | |||
+ | <java5> | ||
+ | import java.util.Comparator; | ||
+ | |||
+ | /** | ||
+ | * 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> { | ||
+ | |||
+ | /** | ||
+ | * A comparator for tables: based on maximum value. | ||
+ | * | ||
+ | * Use as: Table.MAX_COMPARATOR | ||
+ | */ | ||
+ | public final static Comparator<Table> MAX_COMPARATOR = new MaxComparator(); | ||
+ | |||
+ | /** | ||
+ | * A comparator for tables: based on length. | ||
+ | * | ||
+ | * Use as: Table.LENGTH_COMPARATOR | ||
+ | */ | ||
+ | public final static Comparator<Table> LENGTH_COMPARATOR = new LengthComparator(); | ||
+ | |||
+ | /** | ||
+ | * This is a private class implementing the comparator. | ||
+ | */ | ||
+ | private static class MaxComparator implements Comparator<Table> { | ||
+ | |||
+ | /** | ||
+ | * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) | ||
+ | */ | ||
+ | @Override | ||
+ | public int compare(Table table1, Table table2) { | ||
+ | return table1.getMax() - table2.getMax(); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | /** | ||
+ | * This is a private class implementing the comparator. | ||
+ | */ | ||
+ | private static class LengthComparator implements Comparator<Table> { | ||
+ | |||
+ | /** | ||
+ | * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) | ||
+ | */ | ||
+ | @Override | ||
+ | public int compare(Table table1, Table table2) { | ||
+ | return table1.getLength() - table2.getLength(); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | /** | ||
+ | * 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; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * This method makes it easy to get the maximum 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 maximum value in the table. | ||
+ | */ | ||
+ | public int getMax() { | ||
+ | int max = _vector[0]; | ||
+ | for (int i : _vector) | ||
+ | if (i > max) | ||
+ | max = i; | ||
+ | return max; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * This method makes it easy to get the maximum 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 length of table. | ||
+ | */ | ||
+ | public int getLength() { | ||
+ | return _vector.length; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * @see java.lang.Comparable#compareTo(java.lang.Object) | ||
+ | */ | ||
+ | @Override | ||
+ | public int compareTo(Table other) { | ||
+ | return getSum() - other.getSum(); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </java5> | ||
+ | |||
+ | == 3. Comparador de Tabelas de Gatos == | ||
+ | |||
+ | (a publicar) | ||
+ | |||
+ | == Exemplo de Aplicação == | ||
+ | |||
+ | <java5> | ||
+ | /** | ||
+ | * Sample uses. | ||
+ | */ | ||
+ | public class Application { | ||
+ | |||
+ | /** | ||
+ | * @param args | ||
+ | */ | ||
+ | public static void main(String[] args) { | ||
+ | Table t1 = new Table(3); // table with 3 integers | ||
+ | Table t2 = new Table(3); // table with 3 integers | ||
+ | |||
+ | t1.setAll(3); | ||
+ | t2.setAll(90); | ||
+ | |||
+ | System.out.println(t1.compareTo(t2)); // <0 | ||
+ | System.out.println(Table.MAX_COMPARATOR.compare(t1, t2)); // <0 | ||
+ | System.out.println(Table.MAX_COMPARATOR.compare(t1, t1)); // 0 | ||
+ | System.out.println(Table.MAX_COMPARATOR.compare(t2, t2)); // 0 | ||
+ | System.out.println(Table.MAX_COMPARATOR.compare(t2, t1)); // >0 | ||
+ | System.out.println(Table.LENGTH_COMPARATOR.compare(t1, t2)); // 0 (same length) | ||
+ | |||
+ | } | ||
+ | |||
+ | } | ||
+ | </java5> | ||
[[category:OOP]] | [[category:OOP]] | ||
[[category:Teaching]] | [[category:Teaching]] |
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).
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