63 votes

comparaison avec les valeurs null

Nous avons un peu de code qui trie une liste d'adresses en fonction de la distance entre leurs coordonnées. ceci est fait à travers les collections.tri avec un comparateur.

Toutefois, de temps en temps une adresse sans les coordonnées dans la liste provoquant une NullPointerException. Ma première idée pour corriger cela, il faut le comparateur de retour 0 comme dististance pour les adresses où au moins une des coordonnées est nulle. J'ai peur de ce qui pourrait conduire à la corruption de l'ordre de la 'valide' éléments dans la liste.

donc, c'est de revenir un '0' valeurs null données dans un comparateur ok, ou est-il le moyen le plus propre à résoudre ce problème.

90voto

Sjoerd Points 34671

Le manipuler comme null signifie "à l'infini". Ainsi, comp(1234, null) == -1, comp(null, null) == 0, comp(null, 1234) == 1. Avec cela, vous obtenez une cohérence de la commande.

26voto

Cowan Points 17235

Juste pour élargir sur Willi Schönborn réponse, je suis venu ici pour dire que google-collections est exactement ce que vous cherchez ici.

Dans le cas général, il vous suffit d'écrire votre propre Comparator d'ignorer les valeurs null (supposé non nul, de sorte qu'il puisse se concentrer sur l'important logique), puis utiliser la Commande pour manipuler les valeurs null:

Collections.sort(addresses, Ordering.from(new AddressComparator()).nullsLast());

Dans votre cas, il s'agit de données DANS l'Adresse (les Coordonnées) qui est utilisé pour trier, à droite? google-collections est encore plus utile dans ce cas. De sorte que vous peut avoir quelque chose de plus comme:

// Seems verbose at first glance, but you'll probably find yourself reusing 
// this a lot and it will pay off quickly.
private static final Function<Address, Coordinates> ADDRESS_TO_COORDINATES = 
  new Function<Address, Coordinates>() {
      public Coordinates apply(Address in) {
          return in.getCoordinates();
      }
  };

private static final Comparator<Coordinates> COORDINATE_SORTER = .... // existing

puis, quand vous voulez trier:

Collections.sort(addresses,
    Ordering.from(COORDINATE_SORTER)
            .nullsLast()
            .onResultOf(ADDRESS_TO_COORDINATES));

et c'est là que la puissance de google-collections commence vraiment à porter ses fruits.

10voto

Stephen C Points 255558

De mon point de vue sur c'est que rien de ce que vous essayez de faire pour "réparer" l' null coordonnées est juste de poser du papier peint sur les fissures. Ce que vous devez vraiment faire est de trouver et corriger les bogues injecter de fausses null coordonnées.

Dans mon expérience, les infestations de NPE bugs sont souvent provoqués par de mauvaises habitudes de codage:

  • insuffisance de la validation des paramètres d'entrée,
  • à l'aide de null afin d'éviter de créer des tableaux vides ou des collections,
  • de retour null lorsqu'une exception doit avoir été jeté, ou
  • à l'aide de null pour représenter "aucune valeur" lorsqu'il y a une meilleure solution.

(Les meilleures solutions pour le "pas de valeur" problème impliquent généralement la réécriture de code, de sorte que vous n'avez pas besoin de représenter ce et/ou en utilisant une valeur non nulle à la place; par exemple, une Chaîne vide, un exemple, une valeur réservée. Vous ne pouvez pas toujours trouver une meilleure solution, mais vous pouvez souvent.)

Si cela décrit votre application, vous devez passer du temps à la racine les problèmes de code plutôt que de réfléchir à des moyens de cacher les Npe.

9voto

stoilkov Points 1331

Ma solution (peut être utile pour quelqu'un qui cherche ici) est de faire la comparaison à la normale, avec des valeurs null pas remplacé par 0, mais la valeur maximale possible (par exemple en Entier.MAX_VALUE). De retour 0 n'est pas cohérent, si vous avez des valeurs qui sont eux-mêmes des 0. Voici un bon exemple:

        public int compare(YourObject lhs, YourObject rhs) {
            Integer l = Integer.MAX_VALUE;
            Integer r = Integer.MAX_VALUE;
            if (lhs != null) {
                l = lhs.giveMeSomeMeasure();
            }
            if (rhs != null) {
                r = rhs.giveMeSomeMeasure();
            }
            return l.compareTo(r);
        }

Je voulais juste ajouter que vous n'avez pas besoin de la valeur max pour entier. Cela dépend de ce que votre giveMeSomeMeasure() la méthode peut retourner. Par exemple, si vous comparez degrés Celsius pour la météo, vous pouvez régler l et r à -300 ou +300, selon l'endroit où vous souhaitez définir la valeur null objets à la tête ou à la queue de la liste.

3voto

LenW Points 1336

Vous probablement ne voulez pas retourner la valeur 0, que, qui implique les adresses sont équidistants et tu ne sais pas vraiment. C'est un problème classique dans lequel vous essayez de faire face à de mauvaises données d'entrée. Je ne pense pas que sa la responsabilité du comparateur d'essayer et de déterminer dans quelle mesure l'adresse est dans realtive conditions lorsque vous ne connaissez pas la distance. Je voudrais supprimer ces adresses à partir de la liste avant de les trier.

Le hack serait de les déplacer vers le bas de la liste (mais c'est moche !)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X