79 votes

Meilleure pratique de recherche inversée Java enum

J'ai vu qu'il proposait, sur un blog que ce qui suit est un moyen raisonnable de faire du "reverse-lookup" à l'aide de l' getCode(int) dans un enum de Java:

public enum Status {
    WAITING(0),
    READY(1),
    SKIPPED(-1),
    COMPLETED(5);

    private static final Map<Integer,Status> lookup 
            = new HashMap<Integer,Status>();

    static {
        for(Status s : EnumSet.allOf(Status.class))
            lookup.put(s.getCode(), s);
    }

    private int code;

    private Status(int code) {
        this.code = code;
    }

    public int getCode() { return code; }

    public static Status get(int code) { 
        return lookup.get(code); 
    }
}

Pour moi, la carte statique et l'initialiseur statique à la fois comme une mauvaise idée, et ma première pensée serait de la recherche de la manière suivante:

public enum Status {
    WAITING(0),
    READY(1),
    SKIPPED(-1),
    COMPLETED(5);

    private int code;

    private Status(int code) {
        this.code = code;
    }

    public int getCode() { return code; }

    public static Status get(int code) { 
        for(Status s : values()) {
            if(s.code == code) return s;
        }
        return null;
    }
}

Existe-il des problèmes évidents avec la méthode, et est-il recommandé de mettre en œuvre ce type de recherche?

31voto

johna Points 422

Maps.uniqueIndex de Google's Guava est assez pratique pour créer des cartes de recherche.

20voto

Matt Ball Points 165937

Si il y a de plus en hauteur, la statique de la carte est intéressante parce qu'elle offre constante de temps de recherche par code. Votre mise en œuvre du temps de recherche augmente linéairement avec le nombre d'éléments dans l'enum. Pour les petites enums, ce ne sera tout simplement pas contribuer de manière significative.

Un problème avec les deux implémentations (et, sans doute, avec Java enums en général), c'est qu'il y a vraiment un supplément caché valeur qu'un Status pouvez: null. Selon les règles de la logique d'affaires, il peut faire sens pour retourner une réelle valeur d'enum, ou de jeter un Exception, lorsque la recherche "a échoué."

7voto

Paŭlo Ebermann Points 35526

Voici une alternative qui peut être encore un peu plus rapide:

 public enum Status {
    WAITING(0),
    READY(1),
    SKIPPED(-1),
    COMPLETED(5);

    private int code;

    private Status(int code) {
        this.code = code;
    }

    public int getCode() { return code; }

    public static Status get(int code) {
        switch(code) {
            case  0: return WAITING;
            case  1: return READY;
            case -1: return SKIPPED;
            case  5: return COMPLETED;
        }
        return null;
    }
}
 

Bien sûr, ce n'est pas vraiment maintenable si vous voulez pouvoir ajouter plus de constantes plus tard.

6voto

digitaljoel Points 13557

De toute évidence, la carte fournira une recherche de temps constant, contrairement à la boucle. Dans une énumération typique avec peu de valeurs, je ne vois pas de problème avec la recherche de parcours.

-2voto

jjnguy Points 62123

Les deux voies sont parfaitement valables. Et ils ont techniquement le même temps d'exécution Big-Oh.

Cependant, si vous enregistrez d'abord toutes les valeurs sur une carte, vous enregistrez le temps nécessaire pour parcourir l'ensemble à chaque fois que vous souhaitez effectuer une recherche. Donc, je pense que la carte statique et l’initialiseur sont un peu mieux.

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