2008-12-15 7 views
5

Je pense à quelque chose comme ceci:Quel est le meilleur moyen d'obtenir la valeur min et max à partir d'une liste de Comparables qui contiennent des valeurs null?

public static <T extends Comparable<T>> T minOf(T...ts){   
    SortedSet<T> set = new TreeSet<T>(Arrays.asList(ts)); 
    return set.first(); 
} 

public static <T extends Comparable<T>> T maxOf(T...ts){ 
    SortedSet<T> set = new TreeSet<T>(Arrays.asList(ts)); 
    return set.last(); 
} 

Mais est non nul sûr, ce qui est quelque chose que je veux aussi.

Savez-vous une meilleure façon de résoudre ce problème?

EDIT:

Après les commentaires que j'ai aussi essayé min():

public static <T extends Comparable<T>> T minOf(T...ts){   
    return Collections.min(Arrays.asList(ts), new Comparator<T>(){ 

     public int compare(T o1, T o2) { 
      if(o1!=null && o2!=null){ 
       return o1.compareTo(o2); 
      }else if(o1!=null){ 
       return 1; 
      }else{ 
       return -1; 
      } 
     }}); 
} 

Que pensez-vous de cela?

+0

C'est inefficace car vous avez besoin O (n log n) compare, depuis le TreeSet trie efficacement la collection, où n compare suffisent. En outre, vous créez beaucoup de déchets inutiles (Arrays.asList crée une copie de "ts", et le TreeSet n'est pas léger, aussi). – mfx

+0

Arrays.asList ne fait pas de copie du tableau. –

+0

Oui cela fonctionnerait, mais pourquoi ne pas déclarer et nommer ce comparateur autrement, alors c'est réutilisable? Ensuite, au lieu d'utiliser cette fonction minOf, appelez le fichier Collections.min standard avec ce comparateur nommé. Votre code devient beaucoup plus lisible en utilisant les appels de bibliothèque standard. – Pyrolistical

Répondre

39

Qu'est-ce qui ne va pas avec Collections.max?

Et pourquoi vous souciez-vous de la sécurité zéro? Êtes-vous sûr de vouloir autoriser la présence de zéros dans votre collection?

+0

La question était pour max * et * min. Collections.max() va regarder chaque élément. Puis, en faisant Collections.min(), vous regarderez chaque élément. Donc, peut-être trier une seule fois est plus rapide. – Yetti99

+1

@ Yetti99 le tri sera plus lent, car il est 'O (n log n)' et '' max' + min' est 'O (2n)'. Ce qui serait un peu mieux, c'est de faire une seule boucle et mettre à jour à la fois max et min dedans. Et l'OP ne semble pas exiger les deux dans une seule fonction. –

3

Si vous avez vraiment besoin d'exclure "null" du résultat, et vous ne pouvez pas l'empêcher d'être dans votre tableau, alors peut-être vous devriez simplement parcourir le tableau avec une simple boucle et garder la trace du "min "et" max "dans des variables séparées. Vous pouvez toujours utiliser la méthode "compare()" sur chaque objet pour le comparer avec vos valeurs "min" et "max" actuelles. De cette façon, vous pouvez ajouter votre propre code pour vérifier les valeurs NULL et les ignorer.

EDIT: voici un code pour illustrer de quoi je parle. Malheureusement, il y a un cas de bord que vous devez considérer - et si tous les arguments passés sont nuls? Que retourne votre méthode?

public static <T extends Comparable<T>> T minOf(T...ts){ 
    T min = null; 
    for (T t : ts) { 
     if (t != null && (min == null || t.compareTo(min) < 0)) { 
      min = t; 
     } 
    } 
    return min; 
} 

public static <T extends Comparable<T>> T maxOf(T...ts){ 
    T max = null; 
    for (T t : ts) { 
     if (t != null && (max == null || t.compareTo(max) > 0)) { 
      max = t; 
     } 
    } 
    return max; 
} 
1

Vous ne devriez pas mettre en œuvre Comparable à accepter nulle, car il rompt le contrat de l'interface.

De https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html:

Notez que nul n'est pas une instance d'une classe, et e.compareTo (null) devrait lancer une NullPointerException même si e.equals (null) retourne false.

Vous devez créer une nouvelle interface, par ex. ComparableNull à la place.

Voir aussi:

Questions connexes