web-dev-qa-db-fra.com

Compare Java enum values

Existe-t-il un moyen de vérifier si une valeur d'énumération est "supérieure/égale" à une autre valeur?

Je veux vérifier si un niveau d'erreur est "erreur ou supérieur".

42
ripper234

Tous Java énumère les implémentations comparables: http://Java.Sun.com/javase/6/docs/api/Java/lang/Enum.html

Vous pouvez également utiliser la méthode ordinal pour les transformer en ints, la comparaison est alors triviale.

if (ErrorLevel.ERROR.compareTo(someOtherLevel) <= 0) {
  ...
}
54
Chris Vest

Une version beaucoup plus expressive serait

myError.isErrorOrAbove(otherError)

ou

myError.isWorseThan(otherError)

De cette façon, vous pouvez définir l'ordre dans l'énumération et modifier la mise en œuvre en interne si vous le souhaitez. Désormais, les clients de l'énumération peuvent comparer les valeurs sans en connaître les détails.

Une mise en œuvre possible qui serait

public enum ErrorLevel {

    INFO(0),
    WARN(1),
    ERROR(2),
    FATAL(3);

    private Integer severity;

    ErrorLevel(int severity) {
        this.severity = severity;
    }

    public boolean isWorseThan(ErrorLevel other) {
        return this.severity > other.severity;
    }
}

Je ne recommanderais pas non plus d'utiliser la méthode ordinal () pour la comparaison, car lorsque quelqu'un modifie l'ordre des valeurs Enum, vous pouvez obtenir un comportement inattendu.

25
Felix Reckers

En supposant que vous les ayez définis par ordre de gravité, vous pouvez comparer les ordinaux de chaque valeur. L'ordinal est sa position dans sa déclaration d'énumération, où la constante initiale est affectée d'un ordinal de zéro.

Vous obtenez l'ordinal en appelant la méthode ordinal () de la valeur.

8
Rich Seller

Java enum a déjà intégré la méthode compareTo (..) , qui utilise la position enum (alias ordinale) pour en comparer une opposer à d'autres. La position est déterminée en fonction de l'ordre dans lequel les constantes d'énumération sont déclarées, la première constante étant affectée d'un ordinal de zéro.
Si cet arrangement ne convient pas, vous devrez peut-être définir votre propre comparateur en ajoutant des champs internes comme indiqué ci-dessous:

import Java.util.Comparator;

public enum Day {
  MONDAY(1, 3),
  TUESDAY(2, 6),
  WEDNESDAY(3, 5),
  THURSDAY(4, 4),
  FRIDAY(5, 2),
  SATURDAY(6, 1),
  SUNDAY(0, 0);

  private final int calendarPosition;
  private final int workLevel;

  Day(int position, int level) {
    calendarPosition = position;
    workLevel = level;
  }

  int getCalendarPosition(){ return calendarPosition; }  
  int getWorkLevel() { return workLevel;  }

  public static Comparator<Day> calendarPositionComparator = new Comparator<Day>() {
    public int compare(Day d1, Day d2) {
      return d1.getCalendarPosition() - d2.getCalendarPosition();
    }
  };

  public static Comparator<Day> workLevelComparator = new Comparator<Day>() {
    public int compare(Day d1, Day d2) {
      // descending order, harder first
      return d2.getWorkLevel() - d1.getWorkLevel();
    }
  };        
}

Pilote pour vérifier si tout fonctionne:

import Java.util.Arrays;
import Java.util.Collections;
import Java.util.List;

public class EnumTest
{
  public static void main (String[] args) {
     List<Day> allDays = Arrays.asList(Day.values());
     System.out.println("===\nListing days in order of calendar position:");
     Collections.sort(allDays, Day.calendarPositionComparator);
     showItems(allDays);
     System.out.println("===\nListing days in order of work level:");
     Collections.sort(allDays, Day.workLevelComparator);
     showItems(allDays);
  }

  public static void showItems(List<Day> days) {
    for (Day day : days) {
      System.out.println(day.name());
    }
  }
}
5
MaxZoom

Je veux vérifier si un niveau d'erreur est "erreur ou supérieur".

Une telle énumération doit avoir un niveau qui lui est associé. Donc, pour trouver des égaux ou plus, vous devez comparer les niveaux.

L'utilisation de l'ordinal dépend de l'ordre dans lequel les valeurs d'énumération apparaissent. Si vous vous y fiez, vous devez le documenter sinon une telle dépendance peut conduire à un code fragile.

5
Peter Lawrey

Une autre option serait

enum Blah {
 A(false), B(false), C(true);
 private final boolean isError;
 Blah(boolean isErr) {isError = isErr;}
 public boolean isError() { return isError; }
}

D'après votre question, je suppose que vous utilisez enum pour désigner une sorte de valeur de retour, dont certains sont des états d'erreur. Cette implémentation a l'avantage de ne pas avoir à ajouter les nouveaux types de retour à un endroit particulier (puis d'ajuster votre valeur de test), mais présente l'inconvénient d'avoir besoin d'un travail supplémentaire pour initialiser l'énumération.

Poursuivant mon hypothèse un peu plus loin, les codes d'erreur sont-ils quelque chose pour l'utilisateur? Un outil de débogage? Si c'est le dernier, j'ai trouvé que le système de gestion des exceptions était assez bien pour Java.

1
Carl