Mappa conveniente tra enum e int / String


108

Quando lavoro con variabili / parametri che possono accettare solo un numero finito di valori, cerco di usare sempre Java enum , come in

public enum BonusType {
  MONTHLY, YEARLY, ONE_OFF
}

Finché rimango nel mio codice, funziona bene. Tuttavia, spesso ho bisogno di interfacciarmi con altro codice che utilizza plainintString valori (o ) per lo stesso scopo, oppure ho bisogno di leggere / scrivere da / a un database in cui i dati sono memorizzati come un numero o una stringa.

In tal caso, mi piacerebbe avere un modo conveniente per associare ogni valore enum a un intero, in modo tale da poter convertire in entrambi i modi (in altre parole, ho bisogno di un "enum reversibile").

Passare da enum a int è facile:

public enum BonusType {
  public final int id;

  BonusType(int id) {
    this.id = id;
  }
  MONTHLY(1), YEARLY(2), ONE_OFF(3);
}

Quindi posso accedere al valore int come BonusType x = MONTHLY; int id = x.id;.

Tuttavia, non vedo un bel modo per il contrario, ovvero passare da int a enum. Idealmente, qualcosa di simile

BonusType bt = BonusType.getById(2); 

Le uniche soluzioni che potrei trovare sono:

  • Metti un metodo di ricerca nell'enum, che usa BonusType.values()per riempire una mappa "int -> enum", quindi lo memorizza nella cache e lo usa per le ricerche. Funzionerebbe, ma dovrei copiare questo metodo in modo identico in ogni enum che uso :-(.
  • Metti il ​​metodo di ricerca in una classe di utilità statica. Quindi avrei bisogno solo di un metodo di "ricerca", ma dovrei giocherellare con la riflessione per farlo funzionare per un'enumerazione arbitraria.

Entrambi i metodi sembrano terribilmente scomodi per un problema così semplice (?).

Altre idee / intuizioni?


1
I <3 java enum ma li odio proprio per questo motivo! Sembra sempre che siano perfetti a parte un brutto difetto ...
Chris Thompson,

8
per enum-> int puoi semplicemente usareordinal()
davin

1
I tuoi valori id sono decidibili da te (ovvero, non potresti semplicemente usarli .ordinal()) o sono decisi da forze esterne?
Paŭlo Ebermann

2
@davin: Sì, e interrompi il codice nel momento in cui qualcuno riorganizza la dichiarazione enum o elimina un valore nel mezzo. Temo che non sia una soluzione robusta: - /.
sleske

1
@davin che usa "ordinal ()" dovrebbe essere evitato quando possibile, è nelle specifiche della lingua
DPM

Risposte:


37

http://www.javaspecialists.co.za/archive/Issue113.html

La soluzione inizia in modo simile alla tua con un valore int come parte della definizione di enum. Quindi continua a creare un'utilità di ricerca basata sui generici:

public class ReverseEnumMap<V extends Enum<V> & EnumConverter> {
    private Map<Byte, V> map = new HashMap<Byte, V>();
    public ReverseEnumMap(Class<V> valueType) {
        for (V v : valueType.getEnumConstants()) {
            map.put(v.convert(), v);
        }
    }

    public V get(byte num) {
        return map.get(num);
    }
}

Questa soluzione è piacevole e non richiede "giocherellare con la riflessione" perché si basa sul fatto che tutti i tipi di enum ereditano implicitamente l'interfaccia Enum.


Questo non usa l'ordinale? Sleske utilizza un id solo perché l'ordinale cambia quando i valori enum vengono riordinati.
extraneon

No, non usa ordinale. Si basa su un valore int definito in modo esplicito. Quel valore int viene utilizzato come chiave della mappa (restituita da v.convert ()).
Jeff,

2
Mi piace molto questa soluzione; sembra che questo sia il più generale che puoi ottenere.
sleske

+1. La mia unica nota è che userei Numberinvece di Byte, perché il mio valore di supporto potrebbe essere di dimensioni maggiori.
Ivaylo Slavov

3
Leggi davvero e veramente la domanda. Se hai a che fare con un database legacy o un sistema esterno che ha definito numeri interi che non desideri propagare attraverso il tuo codice, questo è esattamente uno di quei casi. L'ordinale è un modo estremamente fragile per persistere il valore di un enum, e oltre a questo è inutile nel caso specifico menzionato nella domanda.
Jeff

327

enum → int

yourEnum.ordinal()

int → enum

EnumType.values()[someInt]

String → enum

EnumType.valueOf(yourString)

enum → String

yourEnum.name()

Una nota a margine:
come hai correttamente sottolineato, ordinal()potrebbe essere "instabile" da versione a versione. Questo è il motivo esatto per cui memorizzo sempre le costanti come stringhe nei miei database. (In realtà, quando uso MySql, li memorizzo come enumerazioni MySql !)


2
+1 Questa è l'ovvia risposta corretta. Nota, tuttavia, esiste un unico metodo di argomento per valueOf che accetta solo una stringa ed esiste fintanto che si utilizza il tipo enum concreto (ad esempio BonusType.valueOf("MONTHLY"))
Tim Bender,

18
L'utilizzo ordinal()mi colpisce come una soluzione problematica, perché si interromperà quando l'elenco dei valori enum viene riorganizzato o un valore viene eliminato. Inoltre, questo è pratico solo se i valori int sono 0 ... n (cosa che spesso ho riscontrato non essere il caso).
sleske

4
@sleske, se inizi a eliminare le costanti, sei comunque nei guai con i dati persistenti esistenti. (Aggiornata la mia risposta a questo proposito.)
aioobe

3
L'utilizzo values()dell'array funzionerà solo se tutti i valori sono indicizzati a 0 per il loro id e sono dichiarati in ordine. (Ho provato questo per verificare che se si dichiara FOO(0), BAR(2), BAZ(1);che values[1] == BARe values[2] == BAZnonostante gli ID passati in.)
Corsika

2
@glowcoder, beh, naturalmente, l'argomento intero è semplicemente un campo nell'oggetto enum. Non ha nulla a che fare con la costante ordinale associata all'oggetto enum (potrebbe anche essere stato a double).
aioobe

29

L'ho trovato sul web, è stato molto utile e semplice da implementare. Questa soluzione NON è stata fatta da me

http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks

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); 
 }

}


s / EnumSet.allOf (Status.class) /Status.values ​​()
jelinson

8

Sembra che le risposte a questa domanda siano obsolete con il rilascio di Java 8.

  1. Non utilizzare ordinal come ordinal è instabile se persistente al di fuori della JVM come un database.
  2. È relativamente facile creare una mappa statica con i valori chiave.

public enum AccessLevel {
  PRIVATE("private", 0),
  PUBLIC("public", 1),
  DEFAULT("default", 2);

  AccessLevel(final String name, final int value) {
    this.name = name;
    this.value = value;
  }

  private final String name;
  private final int value;

  public String getName() {
    return name;
  }

  public int getValue() {
    return value;
  }

  static final Map<String, AccessLevel> names = Arrays.stream(AccessLevel.values())
      .collect(Collectors.toMap(AccessLevel::getName, Function.identity()));
  static final Map<Integer, AccessLevel> values = Arrays.stream(AccessLevel.values())
      .collect(Collectors.toMap(AccessLevel::getValue, Function.identity()));

  public static AccessLevel fromName(final String name) {
    return names.get(name);
  }

  public static AccessLevel fromValue(final int value) {
    return values.get(value);
  }
}

Il secondo parametro di non dovrebbe Collectors.toMap()essere Functions.identity()invece di null?
Adam Michalik

sì, l'ho adottato da una classe helper che uso con guava che converte null in identità.
John Meyer

Questo è un uso accurato delle nuove funzionalità di Java 8. Tuttavia, significa ancora che il codice dovrebbe essere ripetuto in ogni enum - e la mia domanda era di evitare questo boilerplate (strutturalmente) ripetuto.
sleske

5

org.apache.commons.lang.enums.ValuedEnum;

Per risparmiarmi la scrittura di un sacco di codice boilerplate o la duplicazione di codice per ogni Enum, ho usato invece Apache Commons Lang ValuedEnum.

Definizione :

public class NRPEPacketType extends ValuedEnum {    
    public static final NRPEPacketType TYPE_QUERY = new NRPEPacketType( "TYPE_QUERY", 1);
    public static final NRPEPacketType TYPE_RESPONSE = new NRPEPacketType( "TYPE_RESPONSE", 2);

    protected NRPEPacketType(String name, int value) {
        super(name, value);
    }
}

Uso:

int -> ValuedEnum:

NRPEPacketType packetType = 
 (NRPEPacketType) EnumUtils.getEnum(NRPEPacketType.class, 1);

Buona idea, non mi rendevo conto che questo esistesse. Grazie per la condivisione!
Keith P

3

Forse potresti usare qualcosa di simile

interface EnumWithId {
    public int getId();

}


enum Foo implements EnumWithId {

   ...
}

Ciò ridurrebbe la necessità di riflessione nella tua classe di utilità.


Puoi fare un esempio di come utilizzare questo snippet?
IgorGanapolsky

3

In questo codice, per una ricerca permanente e intensa, ho memoria o processo da utilizzare e seleziono la memoria, con array di convertitori come indice. Spero sia utile

public enum Test{ 
VALUE_ONE(101, "Im value one"),
VALUE_TWO(215, "Im value two");
private final int number;
private final byte[] desc;

private final static int[] converter = new int[216];
static{
    Test[] st = values();
    for(int i=0;i<st.length;i++){
        cv[st[i].number]=i;
    }
}

Test(int value, byte[] description) {
    this.number = value;
    this.desc = description;
}   
public int value() {
    return this.number;
}
public byte[] description(){
    return this.desc;
}

public static String description(int value) {
    return values()[converter[rps]].desc;
}

public static Test fromValue(int value){
return values()[converter[rps]];
}
}

2

Usa un'interfaccia per mostrare chi comanda.

public interface SleskeEnum {
    int id();

    SleskeEnum[] getValues();

}

public enum BonusType implements SleskeEnum {


  MONTHLY(1), YEARLY(2), ONE_OFF(3);

  public final int id;

  BonusType(int id) {
    this.id = id;
  }

  public SleskeEnum[] getValues() {
    return values();
  }

  public int id() { return id; }


}

public class Utils {

  public static SleskeEnum getById(SleskeEnum type, int id) {
      for(SleskeEnum t : type.getValues())
          if(t.id() == id) return t;
      throw new IllegalArgumentException("BonusType does not accept id " + id);
  }

  public static void main(String[] args) {

      BonusType shouldBeMonthly = (BonusType)getById(BonusType.MONTHLY,1);
      System.out.println(shouldBeMonthly == BonusType.MONTHLY);

      BonusType shouldBeMonthly2 = (BonusType)getById(BonusType.MONTHLY,1);
      System.out.println(shouldBeMonthly2 == BonusType.YEARLY);

      BonusType shouldBeYearly = (BonusType)getById(BonusType.MONTHLY,2);
      System.out.println(shouldBeYearly  == BonusType.YEARLY);

      BonusType shouldBeOneOff = (BonusType)getById(BonusType.MONTHLY,3);
      System.out.println(shouldBeOneOff == BonusType.ONE_OFF);

      BonusType shouldException = (BonusType)getById(BonusType.MONTHLY,4);
  }
}

E il risultato:

C:\Documents and Settings\user\My Documents>java Utils
true
false
true
true
Exception in thread "main" java.lang.IllegalArgumentException: BonusType does not accept id 4
        at Utils.getById(Utils.java:6)
        at Utils.main(Utils.java:23)

C:\Documents and Settings\user\My Documents>

1
Proprio come con la risposta di Turd Ferguson, questa è la soluzione poco elegante che vorrei evitare / migliorare ...
sleske

Di solito creo le mappature inverse in un blocco {} statico per non dover eseguire il ciclo su valori () ogni volta che chiedo un valore tramite id. Di solito chiamo anche il metodo valueOf (int) per farlo sembrare un po 'come il metodo valueOf (String) già presente per le stringhe (anch'esso parte della domanda dell'OP). Un po 'come l'articolo 33 in Java efficace: tinyurl.com/4ffvc38
Fredrik

@Sleske Aggiornato con una soluzione più raffinata. @Fredrik è interessante, anche se dubito che l'iterazione sarà un problema significativo.
corsiKa

@glowcoder Beh, non dover ripetere più di una volta significa che non importa se lo fai mille volte al secondo dove può essere un problema molto significativo o semplicemente chiamarlo due volte.
Fredrik

@Fredrik Ammetto che ci sono momenti in cui potrebbe essere necessario ottimizzare. Sto anche dicendo che finché non si tratta di un problema di prestazioni identificato, non ottimizzarlo.
corsiKa

2

Sia l' .ordinal()evalues()[i] sono instabili poiché dipendono dall'ordine delle enumerazioni. Quindi se modifichi l'ordine delle enumerazioni o ne aggiungi / elimini alcune il tuo programma si interromperà.

Ecco un metodo semplice ma efficace per mappare tra enum e int.

public enum Action {
    ROTATE_RIGHT(0), ROTATE_LEFT(1), RIGHT(2), LEFT(3), UP(4), DOWN(5);

    public final int id;
    Action(int id) {
        this.id = id;
    }

    public static Action get(int id){
        for (Action a: Action.values()) {
            if (a.id == id)
                return a;
        }
        throw new IllegalArgumentException("Invalid id");
    }
}

Applicarlo per le corde non dovrebbe essere difficile.


Sì, mi rendo conto che potrei farlo o, ancora meglio, utilizzare una mappa per la ricerca inversa, piuttosto che scorrere tutti i valori. L'ho menzionato nella mia domanda e ho anche detto che sto cercando una soluzione migliore, per evitare di avere codice boilerplate in ogni enum.
sleske

2

Un esempio di utilizzo molto pulito di Enum inverso

Passaggio 1 Definire un interfaceEnumConverter

public interface EnumConverter <E extends Enum<E> & EnumConverter<E>> {
    public String convert();
    E convert(String pKey);
}

Passo 2

Crea un nome di classe ReverseEnumMap

import java.util.HashMap;
import java.util.Map;

public class ReverseEnumMap<V extends Enum<V> & EnumConverter<V>> {
    private Map<String, V> map = new HashMap<String, V>();

    public ReverseEnumMap(Class<V> valueType) {
        for (V v : valueType.getEnumConstants()) {
            map.put(v.convert(), v);
        }
    }

    public V get(String pKey) {
        return map.get(pKey);
    }
}

Passaggio 3

Vai alla tua Enumclasse e implementcon EnumConverter<ContentType>e ovviamente sovrascrivi i metodi di interfaccia. È inoltre necessario inizializzare una ReverseEnumMap statica.

public enum ContentType implements EnumConverter<ContentType> {
    VIDEO("Video"), GAME("Game"), TEST("Test"), IMAGE("Image");

    private static ReverseEnumMap<ContentType> map = new ReverseEnumMap<ContentType>(ContentType.class);

    private final String mName;

    ContentType(String pName) {
        this.mName = pName;
    }

    String value() {
        return this.mName;
    }

    @Override
    public String convert() {
        return this.mName;
    }

    @Override
    public ContentType convert(String pKey) {
        return map.get(pKey);
    }
}

Passaggio 4

Ora crea un Communicationfile di classe e chiama il suo nuovo metodo per convertire un Enumin Stringe Stringin Enum. Ho appena messo il metodo principale a scopo di spiegazione.

public class Communication<E extends Enum<E> & EnumConverter<E>> {
    private final E enumSample;

    public Communication(E enumSample) {
        this.enumSample = enumSample;
    }

    public String resolveEnumToStringValue(E e) {
        return e.convert();
    }

    public E resolveStringEnumConstant(String pName) {
        return enumSample.convert(pName);
    }

//Should not put main method here... just for explanation purpose. 
    public static void main(String... are) {
        Communication<ContentType> comm = new Communication<ContentType>(ContentType.GAME);
        comm.resolveEnumToStringValue(ContentType.GAME); //return Game
        comm.resolveStringEnumConstant("Game"); //return GAME (Enum)
    }
}

Fare clic per per una spiegazione completa


1
Questo mi piace davvero molto: da tempo sto cercando una soluzione solida a questo problema. L'unico cambiamento che ho apportato è stato rendere ContentType convert(String pKey)statico, che elimina la necessità della Communicationclasse ed è stato più di mio gradimento. +1
Chris Mantle

1

Non sono sicuro che sia lo stesso in Java, ma i tipi enum in C vengono automaticamente mappati anche a numeri interi, quindi puoi utilizzare il tipo o il numero intero per accedervi. Hai già provato ad accedervi semplicemente con il numero intero?


2
Le enumerazioni in Java non si comportano in questo modo. Sono un tipo esplicito.
Chris Thompson,

Ogni oggetto enum avrebbe un numero interno (ovvero la posizione in cui è stato dichiarato), ed è possibile accedervi tramite il .ordinal()metodo. (Nell'altro modo, usa BonusType.values()[i].) Ma nell'esempio citato sopra, gli indici qui ei valori esterni non coincidono.
Paŭlo Ebermann

1

Domanda davvero fantastica :-) Ho usato una soluzione simile a quella del signor Ferguson qualche tempo fa. La nostra enumerazione decompilata ha questo aspetto:

final class BonusType extends Enum
{

    private BonusType(String s, int i, int id)
    {
        super(s, i);
        this.id = id;
    }

    public static BonusType[] values()
    {
        BonusType abonustype[];
        int i;
        BonusType abonustype1[];
        System.arraycopy(abonustype = ENUM$VALUES, 0, abonustype1 = new BonusType[i = abonustype.length], 0, i);
        return abonustype1;
    }

    public static BonusType valueOf(String s)
    {
        return (BonusType)Enum.valueOf(BonusType, s);
    }

    public static final BonusType MONTHLY;
    public static final BonusType YEARLY;
    public static final BonusType ONE_OFF;
    public final int id;
    private static final BonusType ENUM$VALUES[];

    static 
    {
        MONTHLY = new BonusType("MONTHLY", 0, 1);
        YEARLY = new BonusType("YEARLY", 1, 2);
        ONE_OFF = new BonusType("ONE_OFF", 2, 3);
        ENUM$VALUES = (new BonusType[] {
            MONTHLY, YEARLY, ONE_OFF
        });
    }
}

Vedendo questo è evidente il motivo per cui ordinal()è instabile. È l' iin super(s, i);. Sono anche pessimista che tu possa pensare a una soluzione più elegante di queste che hai già enumerato. Dopotutto le enumerazioni sono classi come qualsiasi classe finale.


1

Per motivi di completezza, ecco un approccio generico per recuperare i valori enum per indice da qualsiasi tipo di enum. La mia intenzione era di rendere il metodo simile a Enum.valueOf (Class, String) . Cordiali saluti, ho copiato questo metodo da qui .

Le questioni relative all'indice (già discusse in profondità qui) si applicano ancora.

/**
 * Returns the {@link Enum} instance for a given ordinal.
 * This method is the index based alternative
 * to {@link Enum#valueOf(Class, String)}, which
 * requires the name of an instance.
 * 
 * @param <E> the enum type
 * @param type the enum class object
 * @param ordinal the index of the enum instance
 * @throws IndexOutOfBoundsException if ordinal < 0 || ordinal >= enums.length
 * @return the enum instance with the given ordinal
 */
public static <E extends Enum<E>> E valueOf(Class<E> type, int ordinal) {
    Preconditions.checkNotNull(type, "Type");
    final E[] enums = type.getEnumConstants();
    Preconditions.checkElementIndex(ordinal, enums.length, "ordinal");
    return enums[ordinal];
}

Non è proprio quello che sto cercando, poiché recupera i valori enum solo dal loro ordinale, non da un ID intero assegnato (vedi la mia domanda). Inoltre, se lo voglio, posso semplicemente usare MyEnumType.values()- non c'è bisogno di un metodo di supporto statico.
sleske

0
Int -->String :

public enum Country {

    US("US",0),
    UK("UK",2),
    DE("DE",1);


    private static Map<Integer, String> domainToCountryMapping; 
    private String country;
    private int domain;

    private Country(String country,int domain){
        this.country=country.toUpperCase();
        this.domain=domain;
    }

    public String getCountry(){
        return country;
    }


    public static String getCountry(String domain) {
        if (domainToCountryMapping == null) {
            initMapping();
        }

        if(domainToCountryMapping.get(domain)!=null){
            return domainToCountryMapping.get(domain);
        }else{
            return "US";
        }

    }

     private static void initMapping() {
         domainToCountryMapping = new HashMap<Integer, String>();
            for (Country s : values()) {
                domainToCountryMapping.put(s.domain, s.country);
            }
        }

0

Avevo bisogno di qualcosa di diverso perché volevo utilizzare un approccio generico. Sto leggendo l'enumerazione da e verso gli array di byte. È qui che mi viene in mente:

public interface EnumConverter {
    public Number convert();
}



public class ByteArrayConverter {
@SuppressWarnings("unchecked")
public static Enum<?> convertToEnum(byte[] values, Class<?> fieldType, NumberSystem numberSystem) throws InvalidDataException {
    if (values == null || values.length == 0) {
        final String message = "The values parameter must contain the value";
        throw new IllegalArgumentException(message);
    }

    if (!dtoFieldType.isEnum()) {
        final String message = "dtoFieldType must be an Enum.";
        throw new IllegalArgumentException(message);
    }

    if (!EnumConverter.class.isAssignableFrom(fieldType)) {
        final String message = "fieldType must implement the EnumConverter interface.";
        throw new IllegalArgumentException(message);
    }

    Enum<?> result = null;
    Integer enumValue = (Integer) convertToType(values, Integer.class, numberSystem); // Our enum's use Integer or Byte for the value field.

    for (Object enumConstant : fieldType.getEnumConstants()) {
        Number ev = ((EnumConverter) enumConstant).convert();

        if (enumValue.equals(ev)) {
            result = (Enum<?>) enumConstant;
            break;
        }
    }

    if (result == null) {
        throw new EnumConstantNotPresentException((Class<? extends Enum>) fieldType, enumValue.toString());
    }

    return result;
}

public static byte[] convertEnumToBytes(Enum<?> value, int requiredLength, NumberSystem numberSystem) throws InvalidDataException {
    if (!(value instanceof EnumConverter)) {
        final String message = "dtoFieldType must implement the EnumConverter interface.";
        throw new IllegalArgumentException(message);
    }

    Number enumValue = ((EnumConverter) value).convert();
    byte[] result = convertToBytes(enumValue, requiredLength, numberSystem);
    return result;
}

public static Object convertToType(byte[] values, Class<?> type, NumberSystem numberSystem) throws InvalidDataException {
    // some logic to convert the byte array supplied by the values param to an Object.
}

public static byte[] convertToBytes(Object value, int requiredLength, NumberSystem numberSystem) throws InvalidDataException {
    // some logic to convert the Object supplied by the'value' param to a byte array.
}
}

Esempio di enumerazione:

public enum EnumIntegerMock implements EnumConverter {
    VALUE0(0), VALUE1(1), VALUE2(2);

    private final int value;

    private EnumIntegerMock(int value) {
        this.value = value;
    }

public Integer convert() {
    return value;
}

}

public enum EnumByteMock implements EnumConverter {
    VALUE0(0), VALUE1(1), VALUE2(2);

    private final byte value;

    private EnumByteMock(int value) {
        this.value = (byte) value;
    }

    public Byte convert() {
        return value;
    }
}

0

Solo perché la risposta accettata non è autonoma:

Codice supporto:

public interface EnumWithCode<E extends Enum<E> & EnumWithCode<E>> {

    public Integer getCode();

    E fromCode(Integer code);
}


public class EnumWithCodeMap<V extends Enum<V> & EnumWithCode<V>> {

    private final HashMap<Integer, V> _map = new HashMap<Integer, V>();

    public EnumWithCodeMap(Class<V> valueType) {
        for( V v : valueType.getEnumConstants() )
            _map.put(v.getCode(), v);
    }

    public V get(Integer num) {
        return _map.get(num);
    }
}

Esempio di utilizzo:

public enum State implements EnumWithCode<State> {
    NOT_STARTED(0), STARTED(1), ENDED(2);

    private static final EnumWithCodeMap<State> map = new EnumWithCodeMap<State>(
            State.class);

    private final int code;

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

    @Override
    public Integer getCode() {
        return code;
    }

    @Override
    public State fromCode(Integer code) {
        return map.get(code);
    }

}

0

dato:

enumerazione pubblica BonusType {MONTHLY (0), YEARLY (1), ONE_OFF (2)}

BonusType bonus = ANNO;

System.out.println (bonus.Ordinal () + ":" + bonus)

Uscita: 1: ANNUALE


0

Se hai un'auto di classe

public class Car {
    private Color externalColor;
}

E la proprietà Color è una classe

@Data
public class Color {
    private Integer id;
    private String name;
}

E vuoi convertire Color in un Enum

public class CarDTO {
    private ColorEnum externalColor;
}

Aggiungi semplicemente un metodo nella classe Color per convertire Color in ColorEnum

@Data
public class Color {
    private Integer id;
    private String name;

    public ColorEnum getEnum(){
        ColorEnum.getById(id);
    }
}

e dentro ColorEnum implementa il metodo getById ()

public enum ColorEnum {
...
    public static ColorEnum getById(int id) {
        for(ColorEnum e : values()) {
            if(e.id==id) 
                return e;
        }
    }
}

Ora puoi usare classMap

private MapperFactory factory = new DefaultMapperFactory.Builder().build();
...
factory.classMap(Car.class, CarDTO.class)
    .fieldAToB("externalColor.enum","externalColor")
    .byDefault()
    .register();
...
CarDTO dto = mapper.map(car, CarDTO.class);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.