Quando usar comparável e comparador

Eu tenho uma lista de objects que preciso classificar em um campo, digamos Score. Sem pensar muito, escrevi uma nova class que implementa o Comparator, que faz a tarefa e funciona.

Agora, olhando para trás, eu estou querendo saber se eu deveria ter, em vez disso, que a class my implemente Comparable ao invés de criar uma nova class que implemente o Comparator. A pontuação é o único campo em que os objects serão ordenados.

  1. O que fiz de aceitável como prática?

  2. É a abordagem correta “Primeiramente, o implemento de class Comparable (para a ordenação natural) e se uma comparação de campo alternativa é necessária, crie uma nova class que implemente o Comparator”?

  3. Se (2) acima for verdadeiro, então isso significa que se deve implementar o Comparador somente depois que eles tiverem implementado a class Comparable? (Assumindo que eu possuo a class original).

Eu diria que um object deve implementar o Comparable se essa for a maneira natural e clara de classificar a class, e qualquer um precisaria classificar a class que geralmente gostaria de fazer dessa maneira.

Se, no entanto, a sorting for um uso incomum da class, ou se a sorting só fizer sentido para um caso de uso específico, um Comparador será a melhor opção.

Dito de outra forma, dado o nome da class, é claro como um comparável seria classificado, ou você precisa recorrer à leitura do javadoc? Se for este último, as probabilidades são que cada caso de uso de ordenação futuro exigiria um comparador, ponto em que a implementação de comparável pode retardar os usuários da class, não acelerá-los.

Use Comparable se você quiser definir um comportamento de ordenação padrão (natural) do object em questão, uma prática comum é usar um identificador técnico ou natural (database?) Do object para isso.

Use o Comparator se você quiser definir um comportamento de ordenação controlável externo , isso pode replace o comportamento de ordenação padrão.

Use Comparable :

  • se o object está no seu controle.
  • se o comportamento de comparação é o principal comportamento de comparação.

Use Comparator :

  • se o object estiver fora do seu controle e você não puder fazê-lo implementar o Comparable .
  • quando você quiser comparar comportamento diferente do comportamento padrão (que é especificado por Comparable ).

Comparáveljava.lang.Comparable: int compareTo(Object o1)

Um object comparável é capaz de se comparar com outro object. A própria class deve implementar a interface java.lang.Comparable para poder comparar suas instâncias.

  • Capaz de comparar o object atual com o object fornecido.
  • Usando isso, podemos implementar only one sort sequence base nas propriedades das instâncias. EX: Person.id
  • Algumas das classs predefinidas, como String, classs Wrapper, Date, Calendar, implementaram a interface Comparable.

Comparadorjava.util.Comparator: int compare(Object o1, Object o2)

Um object de comparação é capaz de comparar dois objects diferentes. A class não está comparando suas instâncias, mas algumas instâncias de outras classs. Essa class de comparação deve implementar a interface java.util.Comparator.

  • Capaz de comparar quaisquer dois Objetos do Mesmo Tipo.
  • Ao usar isso, podemos implementar many sort sequence e nomear cada uma delas, com base nas propriedades das instâncias. EX: Person.id, Person.name, Person.age
  • Podemos implementar a interface do Comparador em nossas classs predefinidas para sorting personalizada.

Exemplo:

 public class Employee implements Comparable { private int id; private String name; private int age; private long salary; // Many sort sequences can be created with different names. public static Comparator NameComparator = new Comparator() { @Override public int compare(Employee e1, Employee e2) { return e1.getName().compareTo(e2.getName()); } }; public static Comparator idComparator = new Comparator() { @Override public int compare(Employee e1, Employee e2) { return Integer.valueOf(e1.getId()).compareTo(Integer.valueOf(e2.getId())); } }; public Employee() { } public Employee(int id, String name, int age, long salary){ this.id = id; this.name = name; this.age = age; this.salary = salary; } // setters and getters. // Only one sort sequence can be created with in the class. @Override public int compareTo(Employee e) { //return Integer.valueOf(this.id).compareTo(Integer.valueOf(e.id)); //return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0))); if (this.id > e.id) { return 1; }else if(this.id < e.id){ return -1; }else { return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0))); } } public static void main(String[] args) { Employee e1 = new Employee(5, "Yash", 22, 1000); Employee e2 = new Employee(8, "Tharun", 24, 25000); List list = new ArrayList(); list.add(e1); list.add(e2); Collections.sort(list); // call @compareTo(o1) Collections.sort(list, Employee.nameComparator); // call @compare (o1,o2) Collections.sort(list, Employee.idComparator); // call @compare (o1,o2) } } 
  • Para sorting personalizada, vamos para o comparador @compare (o1, o2) para outros cenários, vamos para comparáveis ​​@compareTo (o1), sem alterar o código, se quisermos classificar mais de um campo, então usamos o comparador.

Para o Java 8 Lambda: Comparator, consulte o meu post.

Comparável deve ser usado quando você compara instâncias da mesma class.

O comparador pode ser usado para comparar instâncias de classs diferentes.

Comparável é implementado por class que precisa definir uma ordenação natural para seus objects. Como String implementa Comparable.

No caso de alguém querer uma ordem de sorting diferente, ele pode implementar o comparador e definir sua própria maneira de comparar duas instâncias.

Comparador faz tudo o que o comparável faz, mais mais.

| | Comparable | Comparator ._______________________________________________________________________________ Is used to allow Collections.sort to work | yes | yes Can compare multiple fields | yes | yes Lives inside the class you're comparing and serves | | as a “default” way to compare | yes | yes Can live outside the class you're comparing | no | yes Can have multiple instances with different method names | no | yes Input arguments can be a list of | just Object| Any type Can use enums | no | yes

Eu encontrei a melhor abordagem para usar comparadores como classs anônimas da seguinte forma:

 private static void sortAccountsByPriority(List accounts) { Collections.sort(accounts, new Comparator() { @Override public int compare(AccountRecord a1, AccountRecord a2) { return a1.getRank().compareTo(a2.getRank()); } }); } 

Você pode criar várias versões de tais methods dentro da class que está planejando classificar. Então você pode ter:

  • sortAccountsByPriority
  • sortAccountsByType
  • sortAccountsByPriorityAndType

    etc …

Agora, você pode usar esses methods de sorting em qualquer lugar e obter a reutilização de código. Isso me dá tudo o que um comparável seria, mais mais … então eu não vejo qualquer razão para usar comparável em tudo.

Eu diria:

  • se a comparação for intuitiva, então implemente de maneira comparável
  • Se não estiver claro se a sua comparação é intuitiva, use um Comparator, pois é mais explícito e, portanto, mais claro para a pobre alma que precisa manter o código.
  • se houver mais de uma comparação intuitiva, prefiro um Comparador, possivelmente criado por um método de fábrica da class a ser comparado.
  • se a comparação tiver um propósito especial, use Comparator
  • Se no momento de escrever a aula você tiver apenas um caso de uso de ordenação use Comparable.
  • Somente quando você tiver mais de uma estratégia de sorting, implemente um Comparador.

Os pontos seguintes ajudam-no a decidir em que situações se deve usar Comparável e em que Comparador:

1) Availabilty do código

2) Single Versus Multiple Criteria Criteria

3) Arays.sort () e Collection.sort ()

4) Como chaves em SortedMap e SortedSet

5) Mais Número de classs Versus flexibilidade

6) Comparações interclasss

7) Ordem Natural

Para artigos mais detalhados você pode consultar Quando usar comparável e quando usar o comparador

Houve uma pergunta semelhante aqui: Quando uma class deve ser Comparável e / ou Comparadora?

Eu diria o seguinte: Implementar Comparável para algo como uma ordem natural, por exemplo, com base em um ID interno

Implemente um Comparador se você tiver um algoritmo de comparação mais complexo, por exemplo, vários campos e assim por diante.

Se você precisar de ordenação natural de pedidos – Comparável pelo usuário SE precisar de sorting personalizada de pedidos – Use Comparator

Exemplo:

 Class Employee{ private int id; private String name; private String department; } 

Ordenação natural A sorting seria baseada no id, porque seria única e a ordenação de ordem personalizada seria nome e departamento.

Refrências:
Quando uma class deve ser Comparável e / ou Comparativa? http://javarevisited.blogspot.com/2011/06/comparator-and-comparable-in-java.html

Comparável:
Sempre que desejamos armazenar apenas elementos homogêneos e a ordem de sorting natural padrão exigida, podemos ir para a class implementando comparable interface comparable .

Comparador:
Sempre que queremos armazenar elementos homogêneos e heterogêneos e queremos classificar em ordem de sorting personalizada padrão, podemos ir para comparator interface de comparator .

Se a ordenação de objects precisar ser baseada em ordem natural, use Comparable ao passo que, se a sorting precisar ser feita em atributos de objects diferentes, use Comparator in Java.

Diferença principal entre Comparável e Comparador:

 +------------------------------------------------------------------------------------+ ¦ Comparable ¦ Comparator ¦ ¦-----------------------------------------+------------------------------------------¦ ¦ java.lang.Comparable ¦ java.util.Comparator ¦ ¦-----------------------------------------+------------------------------------------¦ ¦ int objOne.compareTo(objTwo) ¦ int compareTo(objOne, objTwo) ¦ ¦-----------------------------------------+------------------------------------------¦ ¦ Negative, if objOne < objTwo ¦ Same as Comparable ¦ ¦ Zero, if objOne == objTwo ¦ ¦ ¦ Positive, if objOne > objTwo ¦ ¦ ¦-----------------------------------------+------------------------------------------¦ ¦ You must modify the clas whose ¦ You build a class separate from to sort. ¦ ¦ instances you want to sort. ¦ the class whose instances you want ¦ ¦-----------------------------------------+------------------------------------------¦ ¦ Only one sort sequemce can be created ¦ Many sort sequences can be created ¦ ¦-----------------------------------------+------------------------------------------¦ ¦ Implemented frequently in the API by: ¦ Meant to be implemented to sort ¦ ¦ String, Wrapper classs, Date, Calandar ¦ instances of third-party classs. ¦ +------------------------------------------------------------------------------------+ 

Uma abordagem muito simples é assumir que a class de entidade em questão seja representada no database e, em seguida, na tabela do database, seria necessário um índice composto de campos da class de entidade? Se a resposta for sim, implemente comparável e use o (s) campo (s) de índice para a ordem de sorting natural. Em todos os outros casos, use o comparador.

Minha necessidade era baseada na data.

Então, eu usei Comparable e funcionou facilmente para mim.

 public int compareTo(GoogleCalendarBean o) { // TODO Auto-generated method stub return eventdate.compareTo(o.getEventdate()); } 

Uma restrição com Comparable é que eles não podem ser usados ​​para Coleções diferentes de List.

Se você possui a class melhor, vá com Comparable . Geralmente Comparator é usado se você não possui a class, mas você tem que usá-lo um TreeSet ou TreeMap porque Comparator pode ser passado como um parâmetro no conctructor de TreeSet ou TreeMap. Você pode ver como usar o Comparator e o Comparable em http://preciselyconcise.com/java/collections/g_comparator.php

Foi-me perguntado a sorting de um intervalo definido de números melhor do que o tempo nlogn em uma das entrevistas. (Não usando o tipo de contagem)

Implementando Interface comparável sobre um object permite que algos de sorting implícitos usem o método compareTo substituído para ordenar os elementos de sorting e isso seria o tempo linear.

  • Comparador para muitos critérios de comparação
  • Comparável quando você tem apenas um critério.

Minha anotação lib para implementar Comparable e Comparator :

 public class Person implements Comparable { private String firstName; private String lastName; private int age; private char gentle; @Override @CompaProperties({ @CompaProperty(property = "lastName"), @CompaProperty(property = "age", order = Order.DSC) }) public int compareTo(Person person) { return Compamatic.doComparasion(this, person); } } 

Clique no link para ver mais exemplos. http://code.google.com/p/compamatic/wiki/CompamaticByExamples