IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Ecrire une méthode générique pour trouver l'élément max dans une liste


Sujet :

Java

  1. #1
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut Ecrire une méthode générique pour trouver l'élément max dans une liste
    Salut,
    c'est une question posé ICI.
    voici ma solution:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      public static <T extends Comparable< T>> T findMax(List<? extends T> list, int begin, int end) {
            ...
        }
    la réponse à cette question dans le tutoriel était de cette forme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public static <T extends Object & Comparable<? super T>>
            T max(List<? extends T> list, int begin, int end) {
    ...
     
    }
    la question est la suivante:
    pour quoi l'utilisation du type à paramètre T extends Comparable<? super T> et non seulement T extends Comparable< T>. quel est l'avantage.

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Le Comparable est souvent typé T extends Comparable<T> pour bien exprimer qu'il n'est comparable qu'à lui même. Cependant, historiquement, c'était compareTo(Object), donc beaucoup d'anciennes classes ont la signature Comparable<Object> qui est un parent de T avec ? super T on ratisse donc plus large dans les classes acceptées.
    le T extends Object est totalement inutile, tout étend Object, inutile de le préciser.


    Enfin, en java 8 on écrirait simplement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public static <T extends Comparable<? super T>> T findMax(List<? extends T> list, int begin, int end) {
        list.subList(begin,end).stream().max(Comparator::naturalOrder).get()
    }

  3. #3
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par tchize_ Voir le message
    Le Comparable est souvent typé T extends Comparable<T> pour bien exprimer qu'il n'est comparable qu'à lui même. Cependant, historiquement, c'était compareTo(Object), donc beaucoup d'anciennes classes ont la signature Comparable<Object> qui est un parent de T avec ? super T on ratisse donc plus large dans les classes acceptées.
    Comparable<T> peut poser problème même avec des classes bien paramétrées... à partir du moment où l'héritage rentre en jeu.


    Il n'est pas obligatoire pour une classe "XX" d'implémenter Comparable<XX>.
    Et surtout en cas d'héritage où l'on pourrait hériter d'une implémentation de Comparable...


    Donc en clair si l'on veut rester compatible avec la majorité des cas, il faut utiliser Comparable<? super T> à la place de Comparable<T>.


    Exemple, avec ta méthode findMax() utilisant Comparable<? super T> on peut écrire le code suivant :
    (sachant que Timestamp hérite de Date et est donc Comparable<Date>)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	List<Date> dates = new ArrayList<>();
    	List<Timestamp> timestamps = new ArrayList<>();
     
    	Date maxDate = findMax(dates, 0, 10);
    	Timestamp maxTimestamp = findMax(timestamps, 0, 10);

    Mais si tu utilise Comparable<T> à la place de Comparable<? super T>, la dernière ligne de ce code génèrera une erreur inutilement...

    a++

  4. #4
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut
    Mais si on utilise Comparable<T> à la place de Comparable<? super T>, la ligne suivante ne génère pas une erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	Date maxTimestamp = findMax(timestamps, 0, 10);

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par win_ubuntu Voir le message
    Mais si on utilise Comparable<T> à la place de Comparable<? super T>, la ligne suivante ne génère pas une erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	Date maxTimestamp = findMax(timestamps, 0, 10);
    Car tu as changé le type de retour, et que T correspond désormais à "Date" au lieu de "Timestamp".
    Cela fonctionne car il y a le <? extends T> sur la liste (pour les mêmes raisons), mais tu perds le type réel de l'objet en retour...


    [edit]
    Grosso modo pour un paramétrage avec T :
    • <T> correspond obligatoirement au type T.
    • <? super T> peut correspondre à T ou n'importe quel de ses types parents.
    • <? extends T> peut correspondre à T ou n'importe quel se ses types enfants.




    a++

  6. #6
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut
    Dans le même contexte, après le processus appelé Erasure :
    Normalement on obtient le même code que ce soit pour Comparable<T> ou Comparable<? super T>.

    voici le code après erasure:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public static  Comparable  findMax(List<Comparable> list, int begin, int end) {
            ...
        }
    donc les génerics sont ajoutés pour augmenter la puissance des compilateurs de détecter les erreurs à la compilation.

  7. #7
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Ce que tu viens de noter est à ne pas faire, ça désactive complètement le mécanisme de check du compilteur et va t'ammener des emmerdes :


    Tu obtiens en retour un Comparable, de quelque chose, même plus une Date
    On ne repère plus les incohérences dans la liste
    Ca génère des warnings à tout va.

  8. #8
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Ce que tu viens de noter est à ne pas faire, ça désactive complètement le mécanisme de check du compilteur et va t'ammener des emmerdes :


    Tu obtiens en retour un Comparable, de quelque chose, même plus une Date
    On ne repère plus les incohérences dans la liste
    Ca génère des warnings à tout va.
    Je ne pense pas que j'ai bien compris votre réponse. peut être que vous avez mal compris mon message.

  9. #9
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par win_ubuntu Voir le message
    donc les génerics sont ajoutés pour augmenter la puissance des compilateurs de détecter les erreurs à la compilation.
    Ouais c'est un but important, mais pas que ça. Ils s'occupent aussi de faire un cast de tes objets en fonction des génériques indiqués.

    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    List<String> desMots = new ArrayList<>();
    desMots.add("Bonjour");
    desMots.add("monde");
     
    String premierMot = desMots.get(0);
    L'équivalent sans générique, c'est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    List desMots = new ArrayList();
    desMots.add("Bonjour");
    desMots.add("monde");
     
    String premierMot = (String)desMots.get(0);
    Avec un joli cast vers String.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Requête pour trouver un ID manquant dans une table
    Par pol2095 dans le forum Requêtes
    Réponses: 3
    Dernier message: 23/07/2014, 15h53
  2. Réponses: 8
    Dernier message: 10/04/2014, 00h03
  3. Réponses: 21
    Dernier message: 04/05/2010, 12h14
  4. Réponses: 12
    Dernier message: 09/11/2009, 19h56
  5. Problème pour trouver les données commune dans une requête
    Par Winterrage dans le forum Langage SQL
    Réponses: 3
    Dernier message: 08/02/2008, 10h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo