2017-05-20 2 views
0

Donc, je suis en train d'apprendre sur Comparator et Comparable et j'ai le problème suivant. J'ai une classe:Quand devrais-je implémenter le comparateur?

public class PhoneBook implements Comparator<Name>{ 

    private SortedMap<Name, Integer> directory ; 

    //class code constructor etc. 

    //this is the method that the compiler wants if implementing Comparator 
    @Override 
    public int compare(Name o1, Name o2) { 

     return o1.firstName.compareTo(o2.firstName); 
     } 
} 

L'autre classe, nom implémente Comparable, et a deux cordes premier et le dernier dans le constructeur. Ce que je ne comprends pas complètement est la fonction de Comparateur, j'ai lu la documentation Java et je sais qu'elle est utilisée pour trier les éléments différemment sans changer la classe Name dans mon exemple elle peut aussi autoriser des valeurs nulles dans certaines situations, mais cette déclaration dans mon constructeur de classe fonctionne très bien, et je ne pas besoin d'implémenter l'interface Comparator dans la classe PhoneBook du tout:

Public PhoneBook(ArrayList<Name> names, ArrayList<Integer> phones) { 
    this.directory = new TreeMap<Name, Integer>(new Comparator<Name>(){ 

     @Override 
     public int compare(Name o1, Name o2) { 

      return o1.firstName.compareTo(o2.firstName); 
     } 

    }); 
    //other constructor code to populate map 
} 

et réalise la fonctionnalité que je veux à réaliser sans la nécessité de mettre en œuvre l'interface Comparator par la classe PhoneBook. Ma question est de savoir quand une classe pourrait vouloir implémenter l'interface Comparator? Existe-t-il une manière différente d'utiliser la carte avec une autre méthode de tri (que celle fournie par l'interface Comparable dans la classe Name) sans lui transmettre une classe anonyme lors de l'initialisation? Je suis désolé si cette question n'est pas assez claire, ou ne convient pas pour ce site web.

Edit: Je comprends l'argument Comparable vs et quand Comparator les utiliser. Ma question est plus sur la façon d'utiliser Comparator. Pouvez-vous trier une carte sans lui passer un nouveau comparateur lors de l'initialisation? Quand est-il une bonne idée pour une classe d'implémenter cette interface?

+1

Impressionnant, vous triez par 'firstName'. Maintenant, ajoutez une fonction à trier par 'lastName'. Et une autre à trier par 'id'. Et une autre à trier par «ville». –

+0

double possible de [Quand faut-il une classe comparable et/ou Comparator?] (Http://stackoverflow.com/questions/1440134/when-should-a-class-be-comparable-and-or-comparator) –

+0

Ou [quand utiliser comparable et Comparator] (http://stackoverflow.com/questions/2266827/when-to-use-comparable-and-comparator) –

Répondre

1

Les classes qui implémentent Comparator ne devrait pas faire autre chose.

Comme la plupart de ces cours ne sont utilisés que dans un seul endroit, il est très fréquent de les mettre en œuvre sans nom, à savoir comme une classe anonyme comme vous l'avez fait dans le second exemple. Toutefois, si vous souhaitez que le Comparator soit réutilisable, il peut être judicieux de créer une classe autonome, par exemple,

le nommer FirstNameComparator dans votre exemple. Notez que dans Java 8+, il est beaucoup plus facile d'utiliser une expression lambda au lieu d'une classe anonyme (puisque c'est logiquement ce qu'une expression lambda devient), et une référence de méthode pour les comparaisons réutilisables.

// Using anonymous class (Java 1.2+) 
this.directory = new TreeMap<Name, Integer>(new Comparator<Name>() { 
    @Override 
    public int compare(Name n1, Name n2) { 
     return n1.getFirstName().compareTo(n2.getFirstName()); 
    } 
}); 
// Reusable named class (Java 1.2+) 
public final class FirstNameComparator implements Comparator<Name> { 
    @Override 
    public int compare(Name n1, Name n2) { 
     return n1.getFirstName().compareTo(n2.getFirstName()); 
    } 
} 

// Then use it like this: 
this.directory = new TreeMap<Name, Integer>(new FirstNameComparator()); 
// Using lambda expression (Java 8+) 
this.directory = new TreeMap<Name, Integer>(
    (n1, n2) -> n1.getFirstName().compareTo(n2.getFirstName()) 
); 
// Using method reference (Java 8+) 
public class PhoneBook { 
    public PhoneBook(ArrayList<Name> names, ArrayList<Integer> phones) { 
     this.directory = new TreeMap<Name, Integer>(PhoneBook::compareFirstName); 
     // other constructor code 
    } 
    private static int compareFirstName(Name n1, Name n2) { // public, if reusable 
     return n1.getFirstName().compareTo(n2.getFirstName()); 
    } 
    // other PhoneBook code 
} 
// Using Comparator helper (Java 8+) 
this.directory = new TreeMap<Name, Integer>(Comparator.comparing(Name::getFirstName));