كيفية الحصول على قيمة التعداد من قيمة سلسلة في جافا؟

StackOverflow https://stackoverflow.com/questions/604424

  •  03-07-2019
  •  | 
  •  

سؤال

لنفترض أن لدي تعدادًا عادلاً

public enum Blah {
    A, B, C, D
}

وأود أن أجد قيمة التعداد لسلسلة، على سبيل المثال "A" التي من شأنها أن تكون Blah.A.كيف سيكون من الممكن القيام بذلك؟

هل Enum.valueOf() الطريقة التي أحتاجها؟إذا كان الأمر كذلك، كيف يمكنني استخدام هذا؟

هل كانت مفيدة؟

المحلول

ونعم، سوف Blah.valueOf("A") تعطيك Blah.A.

لاحظ أن يجب أن يكون اسم أحد بالضبط مباراة، بما في ذلك القضية:. Blah.valueOf("a") وBlah.valueOf("A ") كلا رمي IllegalArgumentException

ويتم إنشاء valueOf() أساليب ثابتة وvalues() في وقت الترجمة ولا تظهر في شفرة المصدر. لا يبدو أنها في جافادوك، على الرغم؛ على سبيل المثال، Dialog.ModalityType يظهر كلتا الطريقتين .

نصائح أخرى

وحل آخر إذا كان النص ليس هو نفسه إلى قيمة التعداد:

public enum Blah {
    A("text1"),
    B("text2"),
    C("text3"),
    D("text4");

    private String text;

    Blah(String text) {
        this.text = text;
    }

    public String getText() {
        return this.text;
    }

    public static Blah fromString(String text) {
        for (Blah b : Blah.values()) {
            if (b.text.equalsIgnoreCase(text)) {
                return b;
            }
        }
        return null;
    }
}

وهنا أداة أنيق يمكنني استخدام:

/**
 * A common method for all enums since they can't have another base class
 * @param <T> Enum type
 * @param c enum type. All enums must be all caps.
 * @param string case insensitive
 * @return corresponding enum, or null
 */
public static <T extends Enum<T>> T getEnumFromString(Class<T> c, String string) {
    if( c != null && string != null ) {
        try {
            return Enum.valueOf(c, string.trim().toUpperCase());
        } catch(IllegalArgumentException ex) {
        }
    }
    return null;
}

وبعد ذلك في صفي التعداد وعادة ما يكون هذا لإنقاذ بعض النسخ:

public static MyEnum fromString(String name) {
    return getEnumFromString(MyEnum.class, name);
}

إذا تتضمن التعدادات الخاصة بك ليست كل مباراة دولية، مجرد تغيير خط Enum.valueOf.

وسيئة للغاية لا يمكنني استخدام T.class لEnum.valueOf كما يتم مسح T.

يجب عليك أيضًا أن تكون حذرًا في قضيتك.دعني أشرح:عمل Blah.valueOf("A") يعمل، ولكن Blah.valueOf("a") لن يعمل.ثم مرة أخرى Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) ستعمل.

يحرر
تغير toUpperCase ل toUpperCase(Locale.ENGLISH) مرتكز على ح.تعليق و ال مستندات جافا

تحرير2على الروبوت يجب عليك استخدام Locale.US, ، مثل يشير سولاي.

استخدم نمط من جوشوا بلوخ، <م> جافا الفعالة :

و(المبسطة الإيجاز)

enum MyEnum {
    ENUM_1("A"),
    ENUM_2("B");

    private String name;

    private static final Map<String,MyEnum> ENUM_MAP;

    MyEnum (String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    // Build an immutable map of String name to enum pairs.
    // Any Map impl can be used.

    static {
        Map<String,MyEnum> map = new ConcurrentHashMap<String, MyEnum>();
        for (MyEnum instance : MyEnum.values()) {
            map.put(instance.getName(),instance);
        }
        ENUM_MAP = Collections.unmodifiableMap(map);
    }

    public static MyEnum get (String name) {
        return ENUM_MAP.get(name);
    }
}

وانظر أيضا:

أوراكل جافا مثال باستخدام التعداد وخريطة حالات

أجل تنفيذ كتل ثابتة في نوع التعداد

كيف يمكنني البحث في التعداد جافا من قيمته سلسلة

إليك طريقة التي يمكن أن تفعل ذلك في أي التعداد، وهي قضية حساسة.

/** 
 * Finds the value of the given enumeration by name, case-insensitive. 
 * Throws an IllegalArgumentException if no match is found.  
 **/
public static <T extends Enum<T>> T valueOfIgnoreCase(
        Class<T> enumeration, String name) {

    for (T enumValue : enumeration.getEnumConstants()) {
        if (enumValue.name().equalsIgnoreCase(name)) {
            return enumValue;
        }
    }

    throw new IllegalArgumentException(String.format(
        "There is no value with name '%s' in Enum %s",
        name, enumeration.getName()
    ));
}

وعن طريق Blah.valueOf(string) هو الأفضل ولكن يمكنك استخدام Enum.valueOf(Blah.class, string) كذلك.

إذا كنت لا تريد أن تكتب فائدة الخاصة بك تستخدم جوجل <فئة = "ما بعد سمة" أ href = "/ الأسئلة / المعلمة / الجوافة" عنوان = "عرض الأسئلة الموسومة" الجوافة "يختلط =" العلامة " > مكتبة الجوافة :

Enums.getIfPresent(Blah.class, "A")

وعلى عكس المدمج في وظيفة جافا ذلك دعونا لك معرفة ما اذا كان هناك موجود في بلاه ولا رمي استثناء.

سنتي 2 هنا:باستخدام Java8 Streams + التحقق من سلسلة محددة:

public enum MyEnum {
    VALUE_1("Super"),
    VALUE_2("Rainbow"),
    VALUE_3("Dash"),
    VALUE_3("Rocks");

    private final String value;

    MyEnum(String value) {
        this.value = value;
    }

    /**
     * @return the Enum representation for the given string.
     * @throws IllegalArgumentException if unknown string.
     */
    public static MyEnum fromString(String s) throws IllegalArgumentException {
        return Arrays.stream(MyEnum.values())
                .filter(v -> v.value.equals(s))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
    }
}

** يحرر **

تمت إعادة تسمية الوظيفة إلى fromString() منذ تسميتها باستخدام هذا الاصطلاح، ستحصل على بعض الفوائد من لغة Java نفسها؛على سبيل المثال:

  1. التحويل المباشر للأنواع في التعليق التوضيحي HeaderParam

في جاوة 8 أو في وقت لاحق، وذلك باستخدام تيارات :

public enum Blah
{
    A("text1"),
    B("text2"),
    C("text3"),
    D("text4");

    private String text;

    Blah(String text) {
        this.text = text;
    }

    public String getText() {
        return this.text;
    }

    public static Optional<Blah> fromText(String text) {
        return Arrays.stream(values())
          .filter(bl -> bl.text.equalsIgnoreCase(text))
          .findFirst();
    }
}

وقد تحتاج إلى هذا:

public enum ObjectType {
    PERSON("Person");

    public String parameterName;

    ObjectType(String parameterName) {
        this.parameterName = parameterName;
    }

    public String getParameterName() {
        return this.parameterName;
    }

    //From String method will return you the Enum for the provided input string
    public static ObjectType fromString(String parameterName) {
        if (parameterName != null) {
            for (ObjectType objType : ObjectType.values()) {
                if (parameterName.equalsIgnoreCase(objType.parameterName)) {
                    return objType;
                }
            }
        }
        return null;
    }
}

واحد عن الإضافة:

   public static String fromEnumName(String parameterName) {
        if (parameterName != null) {
            for (DQJ objType : DQJ.values()) {
                if (parameterName.equalsIgnoreCase(objType.name())) {
                    return objType.parameterName;
                }
            }
        }
        return null;
    }

وهذا سيعود لك القيمة من قبل اسم Stringified التعداد على سبيل المثال إذا قمت بتوفير "شخص" في fromEnumName انها سوف نعود لكم قيمة التعداد أي "شخص"

وهناك طريقة أخرى للقيام بذلك باستخدام ضمني name() طريقة ثابتة من التعداد. واسم بإرجاع سلسلة الدقيقة المستخدمة لإنشاء هذا التعداد والتي يمكن استخدامها للتحقق ضد سلسلة المقدمة:

public enum Blah {

    A, B, C, D;

    public static Blah getEnum(String s){
        if(A.name().equals(s)){
            return A;
        }else if(B.name().equals(s)){
            return B;
        }else if(C.name().equals(s)){
            return C;
        }else if (D.name().equals(s)){
            return D;
        }
        throw new IllegalArgumentException("No Enum specified for this string");
    }
}

والاختبار:

وSystem.out.println(Blah.getEnum("B").name());

//it will print B  B

والإلهام: 10 أمثلة على التعداد في جاوة

والحل باستخدام مكتبات الجوافة. طريقة getPlanet () هي قضية حساسة، لذلك سوف getPlanet ( "الزئبق") العودة Planet.MERCURY.

package com.universe.solarsystem.planets;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Enums;
import com.google.common.base.Optional;

//Pluto and Eris are dwarf planets, who cares!
public enum Planet {
   MERCURY,
   VENUS,
   EARTH,
   MARS,
   JUPITER,
   SATURN,
   URANUS,
   NEPTUNE;

   public static Planet getPlanet(String name) {
      String val = StringUtils.trimToEmpty(name).toUpperCase();
      Optional <Planet> possible = Enums.getIfPresent(Planet.class, val);
      if (!possible.isPresent()) {
         throw new IllegalArgumentException(val + "? There is no such planet!");
      }
      return possible.get();
   }
}

لإضافة إلى الأجوبة السابقة، ومعالجة بعض المناقشات حول القيم الخالية وNPE أنا باستخدام الجوافة اخليارات للتعامل مع حالات تغيب / غير صالحة. هذا وتعمل كبرى لURI / معلمة التوزيع.

public enum E {
    A,B,C;
    public static Optional<E> fromString(String s) {
        try {
            return Optional.of(E.valueOf(s.toUpperCase()));
        } catch (IllegalArgumentException|NullPointerException e) {
            return Optional.absent();
        }
    }
}

لأولئك الذين لا تدرك، وهنا بعض مزيد من المعلومات حول تجنب اغية مع اختياري: HTTPS: // code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional

في جاوة 8 نمط خريطة ثابت، بل هو أسهل وهو لي طريقة أعطيت الأولوية. إذا كنت ترغب في استخدام التعداد مع جاكسون يمكنك تجاوز toString واستخدام ذلك بدلا من اسم، ثم علق مع @JsonValue

public enum MyEnum {
    BAR,
    BAZ;
    private static final Map<String, MyEnum> MAP = Stream.of(MyEnum.values()).collect(Collectors.toMap(Enum::name, Function.identity()));
    public static MyEnum fromName(String name){
        return MAP.get(name);
    }
}

public enum MyEnumForJson {
    BAR("bar"),
    BAZ("baz");
    private static final Map<String, MyEnumForJson> MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toString, Function.identity()));
    private final String value;

    MyEnumForJson(String value) {
        this.value = value;
    }

    @JsonValue
    @Override
    public String toString() {
        return value;
    }

    public static MyEnumForJson fromValue(String value){
        return MAP.get(value);
    }
}
public static MyEnum getFromValue(String value) {
    MyEnum resp = null;
    MyEnum nodes[] = values();
    for(int i = 0; i < nodes.length; i++) {
        if(nodes[i].value.equals(value)) {
            resp = nodes[i];
            break;
        }
    }
    return resp;
}

وO (1) طريقة مستوحاة من الادخار إنشاء رمز التي تستخدم لhashmap.

public enum USER {
        STUDENT("jon",0),TEACHER("tom",1);

        private static final Map<String, Integer> map = new HashMap<>();

        static {
                for (USER user : EnumSet.allOf(USER.class)) {
                        map.put(user.getTypeName(), user.getIndex());
                }
        }

        public static int findIndexByTypeName(String typeName) {
                return map.get(typeName);
        }

        private USER(String typeName,int index){
                this.typeName = typeName;
                this.index = index;
        }
        private String typeName;
        private int index;
        public String getTypeName() {
                return typeName;
        }
        public void setTypeName(String typeName) {
                this.typeName = typeName;
        }
        public int getIndex() {
                return index;
        }
        public void setIndex(int index) {
                this.index = index;
        }

}

java.lang.Enum يحدد عدة طرق مفيدة متاحة لجميع أنواع التعداد في Java:

  • يمكنك استخدام name() طريقة للحصول على اسم أي ثوابت التعداد.السلسلة الحرفية المستخدمة لكتابة ثوابت التعداد هي اسمها.
  • بصورة مماثلة values() يمكن استخدام الطريقة للحصول على مصفوفة من جميع ثوابت التعداد من نوع التعداد.
  • وبالنسبة للسؤال المطروح، يمكنك استخدام valueOf() طريقة لتحويل أي سلسلة إلى ثابت التعداد في Java، كما هو موضح أدناه.
public class EnumDemo06 {
    public static void main(String args[]) {
        Gender fromString = Gender.valueOf("MALE");
        System.out.println("Gender.MALE.name() : " + fromString.name());
    }

    private enum Gender {
        MALE, FEMALE;
    }
}

Output:
Gender.MALE.name() : MALE

في مقتطف الكود هذا، valueOf() تقوم الطريقة بإرجاع نوع التعداد الثابت Gender.MALE، مما يؤدي إلى إرجاع الاسم الذي يتم استدعاؤه "MALE".

مكتبة

وأباتشي العموم لانغ لديه وظيفة ثابتة <أ href ل = "https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/EnumUtils.html#getEnum(java.lang.Class،٪20java.lang.String ) "يختلط =" نوفولو "عنوان =" EnumUtils.getEnum "> org.apache.commons.lang3.EnumUtils.getEnum حيث سيتم تعيين سلسلة إلى نوع التعداد الخاص بك. الجواب نفسه أساسا كما Geoffreys ولكن لماذا القوائم الخاصة بك عندما يكون هناك في البرية بالفعل.

إضافة إلى الإجابة الأعلى تقييمًا، مع أداة مفيدة...

valueOf() يرمي استثناءين مختلفين في الحالات التي لا يحب فيها إدخاله.

  • IllegalArgumentException
  • NullPointerExeption

إذا كانت متطلباتك لا تتضمن أي ضمان بأن السلسلة الخاصة بك ستتطابق بالتأكيد مع قيمة التعداد، على سبيل المثال، إذا كانت بيانات السلسلة تأتي من قاعدة بيانات ويمكن أن تحتوي على إصدار قديم من التعداد، فستحتاج إلى التعامل مع هذه غالباً...

إذن، إليك طريقة قابلة لإعادة الاستخدام كتبتها والتي تسمح لنا بتحديد التعداد الافتراضي الذي سيتم إرجاعه إذا كانت السلسلة التي نمررها غير متطابقة.

private static <T extends Enum<T>> T valueOf( String name , T defaultVal) {
        try {
            return Enum.valueOf(defaultVal.getDeclaringClass() , name);
        } catch (IllegalArgumentException | NullPointerException e) {
            return defaultVal;
        }
    }

استخدامه مثل هذا:

public enum MYTHINGS {
    THINGONE,
    THINGTWO
}

public static void main(String [] asd) {
  valueOf("THINGTWO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGTWO
  valueOf("THINGZERO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGONE
}

وماذا عن؟

public enum MyEnum {
    FIRST,
    SECOND,
    THIRD;

    public static Optional<MyEnum> fromString(String value){
        try{
            return Optional.of(MyEnum.valueOf(value));
        }catch(Exception e){
            return Optional.empty();
        }
    }
}

وفائدة أخرى التقاط بطريقة عكسية. باستخدام قيمة التي تحدد أن التعداد، وليس من اسمها.

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.EnumSet;

public class EnumUtil {

    /**
     * Returns the <code>Enum</code> of type <code>enumType</code> whose a 
     * public method return value of this Enum is 
     * equal to <code>valor</code>.<br/>
     * Such method should be unique public, not final and static method 
     * declared in Enum.
     * In case of more than one method in match those conditions
     * its first one will be chosen.
     * 
     * @param enumType
     * @param value
     * @return 
     */
    public static <E extends Enum<E>> E from(Class<E> enumType, Object value) {
        String methodName = getMethodIdentifier(enumType);
        return from(enumType, value, methodName);
    }

    /**
     * Returns the <code>Enum</code> of type <code>enumType</code> whose  
     * public method <code>methodName</code> return is 
     * equal to <code>value</code>.<br/>
     *
     * @param enumType
     * @param value
     * @param methodName
     * @return
     */
    public static <E extends Enum<E>> E from(Class<E> enumType, Object value, String methodName) {
        EnumSet<E> enumSet = EnumSet.allOf(enumType);
        for (E en : enumSet) {
            try {
                String invoke = enumType.getMethod(methodName).invoke(en).toString();
                if (invoke.equals(value.toString())) {
                    return en;
                }
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }

    private static String getMethodIdentifier(Class<?> enumType) {
        Method[] methods = enumType.getDeclaredMethods();
        String name = null;
        for (Method method : methods) {
            int mod = method.getModifiers();
            if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && !Modifier.isFinal(mod)) {
                name = method.getName();
                break;
            }
        }
        return name;
    }
}

مثال:

public enum Foo {
    ONE("eins"), TWO("zwei"), THREE("drei");

    private String value;

    private Foo(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

وEnumUtil.from(Foo.class, "drei") يعود Foo.THREE، لأنها سوف تستخدم getValue لتتناسب مع "كلية دبي العقارية"، والذي هو الجمهور فريدة من نوعها، ليس نهائيا وليس أسلوب ثابت في فو. في حال فو لديها أكثر من التركيز على طريقة العام، وليس نهائي وغير ثابت، على سبيل المثال، getTranslate التي ترجع "كلية دبي العقارية"، وطريقة أخرى يمكن استخدامها: EnumUtil.from(Foo.class, "drei", "getTranslate")

وكما لم يذكر في إصدار switch بعد أن أعرض عليه (إعادة استخدام التعداد OP و):

  private enum Blah {
    A, B, C, D;

    public static Blah byName(String name) {
      switch (name) {
        case "A":
          return A;
        case "B":
          return B;
        case "C":
          return C;
        case "D":
          return D;
        default:
          throw new IllegalArgumentException(
            "No enum constant " + Blah.class.getCanonicalName() + "." + name);
      }
    }
  }

وبما أن هذا لا تعطي أي قيمة إضافية إلى أسلوب valueOf(String name)، إلا أنه من المنطقي لتحديد وسيلة إضافية إذا كنا نريد أن يكون سلوك مختلف. وإذا كنا لا نريد لرفع IllegalArgumentException يمكننا تغيير تنفيذها:

  private enum Blah {
    A, B, C, D;

    public static Blah valueOfOrDefault(String name, Blah defaultValue) {
      switch (name) {
        case "A":
          return A;
        case "B":
          return B;
        case "C":
          return C;
        case "D":
          return D;
        default:
          if (defaultValue == null) {
            throw new NullPointerException();
          }
          return defaultValue;
      }
    }
  }

ومن خلال توفير قيمة افتراضية نبقي في عقد من Enum.valueOf(String name) دون طرح IllegalArgumentException بهذه الطريقة التي يتم إرجاعها في أي حال من الأحوال null. ولذلك نحن رمي NullPointerException إذا كان الاسم null وفي حالة default إذا defaultValue هو null. هذه هي الطريقة التي يعمل valueOfOrDefault.

وهذا النهج يعتمد تصميم Map واجهة التي توفر Map.getOrDefault(Object key, V defaultValue) طريقة اعتبارا من جافا 8.

وأود أن استخدام هذا النوع من عملية تحليل الأوامر كسلاسل في التعدادات. لدي عادة واحدة من التعدادات بأنها "غير معروف" حتى أنه يساعد على أن يكون هذا عاد عندما لم يتم العثور على الآخرين (حتى على أساس كل حالة حساسة) بدلا من فارغة (أن معنى عدم وجود قيمة). ومن هنا يمكنني استخدام هذا النهج.

static <E extends Enum<E>> Enum getEnumValue(String what, Class<E> enumClass) {
    Enum<E> unknown=null;
    for (Enum<E> enumVal: enumClass.getEnumConstants()) {  
        if (what.compareToIgnoreCase(enumVal.name()) == 0) {
            return enumVal;
        }
        if (enumVal.name().compareToIgnoreCase("unknown") == 0) {
            unknown=enumVal;
        }
    }  
    return unknown;
}

وأسرع طريقة للحصول على اسم التعداد هي لإنشاء خريطة النص التعداد وقيمة عند بدء تشغيل التطبيق، والحصول على اسم استدعاء Blah.getEnumName وظيفة ():

public enum Blah {
    A("text1"),
    B("text2"),
    C("text3"),
    D("text4");

    private String text;
    private HashMap<String, String> map;
    Blah(String text) {
    this.text = text;
    }

    public String getText() {
      return this.text;
    }

    static{
      createMapOfTextAndName();
    }

    public static void createMapOfTextAndName() {
        map = new HashMap<String, String>();
        for (Blah b : Blah.values()) {
             map.put(b.getText(),b.toString());
        }
    }
    public static String getEnumName(String text) {
        return map.get(text.toLowerCase());
    } 
}

والتعداد مفيد جدا، لقد تم استخدام Enum الكثير لإضافة وصف لبعض الحقول في لغات مختلفة، كما في المثال التالي:

public enum Status {

    ACT(new String[] { "Accepted", "مقبول" }),
    REJ(new String[] { "Rejected", "مرفوض" }),
    PND(new String[] { "Pending", "في الانتظار" }),
    ERR(new String[] { "Error", "خطأ" }),
    SNT(new String[] { "Sent", "أرسلت" });

    private String[] status;

    public String getDescription(String lang) {
        return lang.equals("en") ? status[0] : status[1];
    }

    Status(String[] status) {
        this.status = status;
    }
}

وبعد ذلك يمكنك استرداد وصف أساس حيوي في رمز اللغة تمريرها إلى getDescription(String lang) طريقة، على سبيل المثال:

String statusDescription = Status.valueOf("ACT").getDescription("en");
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top