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

From Wiki**3

< Classes Internas (Java)
Line 1: Line 1:
 
{{TOCright}}
 
{{TOCright}}
= Interfaces para Comparações =
 
<p>A interface  <strong>Comparable&lt;T&gt;</strong> exige &agrave;s classes que a implementam a cria&ccedil;&atilde;o de um m&eacute;todo (  <strong>T</strong> &eacute; um tipo)</p>
 
 
<java5>
 
int compareTo(T other);
 
</java5>
 
 
<p>Este m&eacute;todo permite estabelecer uma ordem natural sobre objectos do tipo utilizado para parametrizar a interface. Colec&ccedil;&otilde;es desses objectos podem ent&atilde;o ser ordenadas utilizando m&eacute;todos pr&eacute;-definidos (e.g.,  <strong>Collections.sort</strong> ou  <strong>Arrays.sort</strong>).</p>
 
<p>O m&eacute;todo  <strong>compareTo</strong> deve retornar um inteiro menor que zero, zero, ou maior que zero, caso um objecto seja "menor", igual (  <strong>equals</strong>), ou "maior" que outro objecto. Como a refer&ecirc;ncia  <strong>null</strong> n&atilde;o representa nenhum objecto, se passada como argumento, n&atilde;o dever&aacute; ser retornado nenhum valor, devendo as implementa&ccedil;&otilde;es lan&ccedil;ar  <strong>NullPointerException</strong>. No exemplo seguite, a ordem natural &eacute; definida pela idade do gato.</p>
 
 
<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>
 
 
<p>Recordar que  <strong>equals</strong> deve retornar  <strong>false</strong> quando &eacute; passada uma refer&ecirc;ncia  <strong>null</strong> como argumento.</p>
 
<p>Semelhante ao uso da interface  <strong>Comparable&lt;T&gt;</strong>, mas sem definir uma ordem natural para os objectos de uma classe, a interface  <strong>Comparator&lt;T&gt;</strong> permite criar classes (implementa&ccedil;&otilde;es), cujos objectos representam fun&ccedil;&otilde;es de compara&ccedil;&atilde;o entre dois objectos da classe utilizada como par&acirc;metro do tipo do comparador. O m&eacute;todo exigido pela interface  <strong>Comparator&lt;T&gt;</strong> &eacute;:</p>
 
 
<java5>
 
int compare(T um, T outro);
 
</java5>
 
 
<p>O uso &eacute; an&aacute;logo ao da interface  <strong>Comparable&lt;T&gt;</strong>, mas n&atilde;o compromete uma classe com nenhuma fun&ccedil;&atilde;o de compara&ccedil;&atilde;o especial. Considerando o exemplo do gato, a defini&ccedil;&atilde;o seguinte permitiria, por exemplo, ordenar gatos por nome (  <strong>String</strong> implementa  <strong>Comparable&lt;String&gt;</strong>, definindo ordem lexicogr&aacute;fica).</p>
 
 
<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>
 
 
<p>Recordar que a compatibilidade com  <strong>equals</strong> e a simetria da compara&ccedil;&atilde;o s&atilde;o como para o caso de  <strong>compareTo</strong> (acima).</p>
 
 
== Problema ==
 
== Problema ==
  

Revision as of 00:42, 16 October 2013

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>

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
{ /** * A comparator for tables: based on maximum value. * * Use as: Table.MAX_COMPARATOR */ public final static Comparator
MAX_COMPARATOR = new MaxComparator(); /** * A comparator for tables: based on length. * * Use as: Table.LENGTH_COMPARATOR */ public final static Comparator
LENGTH_COMPARATOR = new LengthComparator(); /** * This is a private class implementing the comparator. */ private static class MaxComparator implements Comparator
{ /** * @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
{ /** * @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 number of 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. * * In this case, we are not actually iterating, since it is much easier and * efficient to access the length attribute. * * @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>