web-dev-qa-db-fra.com

Comment créer une méthode générique pour renvoyer un tableau des valeurs enum au lieu de ses constantes?

J'ai un enum avec des descriptions en tant que chaîne. C'est l'énum.

public enum tabs
{
    A("Actual data"),
    B("Bad data"),
    C("Can data"),
    D("Direct data");

    private String description;
    tabs(String desc)
    {
        this.description = desc;
    }


    public String getDescription()
    {
        return this.description;
    }
}

Maintenant, si j'ai besoin des données pour A, je ferais juste 

tabs.A.description

Je suis en train de créer une méthode générique pour renvoyer les valeurs. 

J'ai réussi à utiliser la méthode générique ci-dessous pour accepter un type enum comme argument. Il retourne un tableau des constantes enum. Mais je souhaite en réalité qu’il renvoie un tableau des valeurs .. c’est-à-dire {"Données réelles", "Données incorrectes", "Données disponibles", "Données directes"}.

public static String[] getActualTabs(Class<? extends Enum<?>> e) 
{
    return Arrays.stream(e.getEnumConstants()).map(Enum::name).toArray(String[]::new);
}

Quelles options ai-je pour y parvenir?

12
SteroidKing666

Vous pouvez passer un mappeur Function pour mapper les constantes enum dans Strings:

public static <T extends Enum<T>> String[] getActualTabs(Class<T> e, Function<? super T, String> mapper) 
{
    return Arrays.stream(e.getEnumConstants()).map(mapper).toArray(String[]::new);
}

Usage:

System.out.println(Arrays.toString(getActualTabs(tabs.class,tabs::getDescription)));

Sortie:

[Actual data, Bad data, Can data, Direct data]
11
Eran

Je vais d'abord tirer getDescription sur une interface et m'assurer que tous les enums de votre projet l'implémentent:

public interface HasDescription {
    String getDescription();
}

Et ensuite, utilisez-le dans votre méthode générique:

public static String[] getActualTabs(Class<? extends Enum<?> & HasDescription> e) {
    return Arrays.stream(e.getEnumConstants())
                 .map(HasDescription::getDescription)
                 .toArray(String[]::new);
}
4
Mureinik

Les deux réponses sont très belles.

Mais il existe une autre variante qui pourrait être supérieure car elle est encore plus largement utilisable:

public static <T> String[] getActualTabs(T[] values, Function<? super T, String> mapper) {
    return Arrays.stream(values)
                 .map(mapper)
                 .toArray(String[]::new);
}

public static <T extends HasDescription> String[] getActualTabs(T[] values) {
    return Arrays.stream(values)
                 .map(HasDescription::getDescription)
                 .toArray(String[]::new);
    // or just: return getActualTabs(values, HasDescription::getDescription);
}

Cette mise en œuvre présente l'avantage de ne pas gâcher la réflexion.

Au lieu de cela, vous les appelleriez comme suit:

String[] tabs1 = getActualTabs(Tabs.values())
String[] tabs2 = getActualTabs(Tabs.values(), Tabs::getDescription)

Notez qu'il peut être utile de renommer les fonctions, e. g. getStringifiedValues() ou toDescriptions().

Avertissement: non testé, mais devrait fonctionner, à mon humble avis.

0
glglgl