【问题标题】:Getting all names in an enum as a String[]将枚举中的所有名称作为 String[]
【发布时间】:2012-11-26 19:46:52
【问题描述】:

将枚举元素的名称作为Strings 的数组获取的最简单和/或最短的方法是什么?

我的意思是,例如,如果我有以下枚举:

public enum State {
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;

    public static String[] names() {
        // ...
    }
}

names() 方法将返回数组 { "NEW", "RUNNABLE", "BLOCKED", "WAITING", "TIMED_WAITING", "TERMINATED" }

【问题讨论】:

  • 为什么没有一个原生的 Enum 方法可以做到完全超出我的范围......还有一个 get(index) 来简化 value() 的获取

标签: java arrays enums


【解决方案1】:

这是任何enum 类的单行代码:

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

Pre Java 8 仍然是单行的,尽管不那么优雅:

public static String[] getNames(Class<? extends Enum<?>> e) {
    return Arrays.toString(e.getEnumConstants()).replaceAll("^.|.$", "").split(", ");
}

你会这样称呼:

String[] names = getNames(State.class); // any other enum class will work

如果您只想为硬编码的枚举类做一些简单的事情:

public static String[] names() {
    return Arrays.toString(State.values()).replaceAll("^.|.$", "").split(", ");
}

【讨论】:

  • 不是完成这项工作的最快方法,但很好的正则表达式。
  • 在 Java 8 解决方案中,在方法范围之外,您可以使用 e.getEnumConstants() 而不是 YourEnumName.values()
  • @Eido95 using YourEnumName.values() 正在调用类的静态方法,该方法不能用于 any 枚举。使用 getEnumConstants() 适用于 any 枚举类。这种方法的想法是重新创建一个实用方法,您可以像答案的最后一行一样调用它。
  • 如果你想为你的枚举自定义标签,在你的枚举类中覆盖 toString()。
  • 你能解释一下Class&lt;? extends Enum&lt;?&gt;&gt; e吗?
【解决方案2】:

为名称创建一个String[] 数组并调用返回所有枚举值的静态values() 方法,然后遍历这些值并填充名称数组。

public static String[] names() {
    State[] states = values();
    String[] names = new String[states.length];

    for (int i = 0; i < states.length; i++) {
        names[i] = states[i].name();
    }

    return names;
}

【讨论】:

  • 为什么调用values() 13次,每次生成一个新数组,而不是把数组缓存在一个局部变量中?为什么要使用可覆盖的 toString() 而不是 name()
  • @JBNizet heheh,我实际上在我的 IDE 中尝试过这个方法,并且懒得创建一个状态数组我猜,呵呵,反正我现在编辑了它:)
  • 您仍然没有返回名称,而是返回 toString() 值。
  • @JBNizet 嗯,tbh,直到现在我才知道有一个 name() 方法。我多么愚蠢 :P 谢谢你让我知道 :)
  • 我接受了这个答案,但我提交了一个改进代码的修改,使其更易于阅读。
【解决方案3】:

这是使用Apache Commons Lang 3 的优雅解决方案:

EnumUtils.getEnumList(State.class)

虽然它返回一个列表,但您可以使用list.toArray()轻松转换列表

【讨论】:

  • EnumUtils.getEnumList(enumClass) 返回枚举值,而不是字符串。您可以使用EnumUtils.getEnumMap(enumClass).keySet(),但顺序可能不同。
【解决方案4】:

如果您可以使用 Java 8,则效果很好(替代 Yura 的建议,效率更高):

public static String[] names() {
    return Stream.of(State.values()).map(State::name).toArray(String[]::new);
}

【讨论】:

    【解决方案5】:

    使用 java 8:

    Arrays.stream(MyEnum.values()).map(Enum::name)
                        .collect(Collectors.toList()).toArray();
    

    【讨论】:

    • 虽然它可能有效,但这种实现效率很低,首先创建一个 ArrayList,添加所有元素,然后创建一个数组并再次复制所有内容。
    • 很快“每个人”都会使用流来完成最基本的操作......这不是一个好主意。
    • 考虑到枚举中的元素数量通常很少,我认为 Yura 的解决方案适用于许多用例。自然要视具体情况而定……
    【解决方案6】:

    我会这样写

    public static String[] names() {
    
        java.util.LinkedList<String> list = new LinkedList<String>();
        for (State s : State.values()) {
            list.add(s.name());
        }
    
        return list.toArray(new String[list.size()]);
    }
    

    【讨论】:

      【解决方案7】:

      另一种方式:

      第一个

      Arrays.asList(FieldType.values())
                  .stream()
                  .map(f -> f.toString())
                  .toArray(String[]::new);
      

      其他方式

      Stream.of(FieldType.values()).map(f -> f.toString()).toArray(String[]::new);
      

      【讨论】:

      • this 的情况下,toString() 有效,但在一般情况下它不起作用,因为 toString() 可以被覆盖。使用 .name() 可靠地获取实例 name 作为字符串。
      【解决方案8】:

      这样的事情会做:

      public static String[] names() {
        String[] names = new String[values().length];
        int index = 0;
      
        for (State state : values()) {
          names[index++] = state.name();
        }
      
        return names;
      }
      

      The documentation recommends using toString() instead of name() in most cases,但您已在此处明确要求提供姓名。

      【讨论】:

      • 虽然不是特别重要,但在这种情况下,常规 for 循环比 foreach 循环提供更好的性能。另外,values() 在只需要调用一次时会被调用两次。
      • @Vulcan 我认为性能只有在运行数十万次时才会成为问题。此外,values() 是编译器生成的方法,所以我猜它已经很优化了。最后,我记得在某处读到 for-each 循环比标准的增量 for 循环更有效,但话又说回来 - it just doesn't matter
      • @Konstantin 考虑到 Java 中的 foreach 循环是使用标准 for 循环实现的,而您读到的 foreach 循环效率更高是不正确的。
      • @sage88 我指的是 for 循环,其中您使用数字索引检索元素,您在每个循环中递增。例如:for (int i = 0; i &lt; a.length; i++) /* do stuff */; 在这种情况下,for-each 循环实际上是,效率更高。对此事的快速搜索给了我们这个:stackoverflow.com/questions/2113216/…
      • @Konstantin 任何时候你有一个允许随机访问的数据结构,就像枚举值一样,它返回一个数组,C 风格的 for 循环比使用 for each 循环更快。 for each 循环必须生成一个迭代器,这会使其变慢。您发布的链接提供了一个使用 get(i) 在链表上使用标准 for 循环的示例,这当然更糟。当使用非随机访问数据结构时,for each 循环更快,但在数组上它有更大的开销。此外,由于它是一个原始数组,而不是 ArrayList,因此 .size() 不会影响性能。
      【解决方案9】:

      我会这样做(但我可能会将名称设为不可修改的集合而不是数组):

      import java.util.Arrays;
      enum State {
          NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED;
          public static final String[] names=new String[values().length];
          static {
              State[] values=values();
              for(int i=0;i<values.length;i++)
                  names[i]=values[i].name();
          }
      }
      public class So13783295 {
          public static void main(String[] args) {
              System.out.println(Arrays.asList(State.names));
          }
      }
      

      【讨论】:

      • 如果我需要重复获取枚举名称,我也会这样做,但由于 names() 方法只被谨慎调用,我认为当场生成一个数组很好。
      【解决方案10】:

      我的解决方案,处理字符串(不是最快的,但很紧凑):

      public enum State {
          NEW,
          RUNNABLE,
          BLOCKED,
          WAITING,
          TIMED_WAITING,
          TERMINATED;
      
          public static String[] names() {
              String valuesStr = Arrays.toString(State.values());
              return valuesStr.substring(1, valuesStr.length()-1).replace(" ", "").split(",");
          }
      }
      

      【讨论】:

      • 和 java7 兼容!
      【解决方案11】:

      普通方式(双关语):

      String[] myStringArray=new String[EMyEnum.values().length];
      for(EMyEnum e:EMyEnum.values())myStringArray[e.ordinal()]=e.toString();
      

      【讨论】:

        【解决方案12】:

        得到了简单的解决方案

        Arrays.stream(State.values()).map(Enum::name).collect(Collectors.toList())
        

        【讨论】:

          【解决方案13】:

          我也有同样的需求并使用泛型方法(在 ArrayUtils 类中):

          public static <T> String[] toStringArray(T[] array) {
              String[] result=new String[array.length];
              for(int i=0; i<array.length; i++){
                  result[i]=array[i].toString();
              }
              return result;
          }
          

          只需在枚举中定义一个 STATIC...

          public static final String[] NAMES = ArrayUtils.toStringArray(values());
          

          Java 枚举确实缺少 names() 和 get(index) 方法,它们真的很有帮助。

          【讨论】:

            【解决方案14】:

            我对@Bohemian 的解决方案做了一些测试。使用 naive loop 时性能更好。

            public static <T extends Enum<?>> String[] getEnumNames(Class<T> inEnumClass){
                T [] values = inEnumClass.getEnumConstants();
                int len = values.length;
                String[] names = new String[len];
                for(int i=0;i<values.length;i++){
                    names[i] = values[i].name();
                }
                return names;
            }
            
            //Bohemian's solution
            public static String[] getNames(Class<? extends Enum<?>> e) {
                return Arrays.stream(e.getEnumConstants()).map(Enum::name).toArray(String[]::new);
            }
            

            【讨论】:

            • 你应该给出关于性能的统计数据,然后人们可以自己判断性能损失是否显着。我想大多数人不会有 100+ 或 1000+ 的枚举值。
            【解决方案15】:

            org.apache.commons.lang3.EnumUtils.getEnumMap(State.class).keySet()

            【讨论】:

            【解决方案16】:

            与接受的答案非常相似,但是自从我了解了 EnumSet,我忍不住到处使用它。因此,对于更简洁的(Java8)答案:

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

            【讨论】:

              【解决方案17】:

              想要最短的可以试试

              public static String[] names() {
                  String test = Arrays.toString(values());
                  return text.substring(1, text.length()-1).split(", ");
              }
              

              【讨论】:

              • 不是最短的 :) 查看我的单行答案(仍然只调用一次 vales()
              【解决方案18】:

              只是一个想法:也许您不需要创建一个方法来将枚举的值作为字符串数组返回。

              为什么需要字符串数组?如果您需要这样做,也许您只需要在使用它们时转换这些值。

              例子:

              for (State value:values()) {
                  System.out.println(value); // Just print it.
              }
              

              for (State value:values()) {
                  String x = value.toString(); // Just iterate and do something with x.
              }
              

              // If you just need to print the values:
              System.out.println(Arrays.toString(State.values()));
              

              【讨论】:

                【解决方案19】:

                在 Java 7 或更早版本中实现此目的的另一种方法是使用 Guava:

                public static String[] names() {
                    return FluentIterable.from(values()).transform(Enum::name).toArray(String.class);
                }
                

                【讨论】:

                  【解决方案20】:

                  试试这个:

                  public static String[] vratAtributy() {
                      String[] atributy = new String[values().length];
                      for(int index = 0; index < atributy.length; index++) {
                          atributy[index] = values()[index].toString();
                      }
                      return atributy;
                  }
                  

                  【讨论】:

                    【解决方案21】:

                    您可以将枚举值放入字符串列表并转换为数组:

                        List<String> stateList = new ArrayList<>();
                    
                                for (State state: State.values()) {
                                    stateList.add(state.toString());
                                }
                    
                        String[] stateArray = new String[stateList.size()];
                        stateArray = stateList.toArray(stateArray);
                    

                    【讨论】:

                      【解决方案22】:

                      最简单的方法:

                      Category[] category = Category.values();
                      for (int i = 0; i < cat.length; i++) {
                           System.out.println(i  + " - " + category[i]);
                      }
                      

                      Category 是Enum 名称

                      【讨论】:

                        【解决方案23】:

                        可以通过“Enum::name”获取枚举字符串值

                        public static String[] names() {
                            return Arrays.stream(State.values()).map(Enum::name).toArray(String[]::new);
                        }
                        

                        此实现不需要额外的“函数”和“字段”。只需添加此函数即可获得您想要的结果。

                        【讨论】:

                          【解决方案24】:

                          基于 Bohemian 对 Kotlin 的回答:

                          使用replace() 而不是replaceAll()

                          Arrays.toString(MyEnum.values()).replace(Regex("^.|.$"), "").split(", ").toTypedArray()
                          

                          旁注:转换为.toTypedArray() 以用于AlertDialogsetSingleChoiceItems,例如。

                          【讨论】:

                            【解决方案25】:
                            enum CardType {
                                CLUB, DIAMOND, HEART, SPADE;
                            
                            }
                            
                            public class Control {
                                public static void main(String[] args) {
                            
                                    String[] cardsArray = new String[CardType.values().length];
                                    int i = 0;
                            
                                    for (CardType cardType : CardType.values()){
                                        cardsArray[i] = cardType.name();
                                        i++;
                                    }
                                    //to output the array
                                    for (int j = 0; j < CardType.values().length; j++){
                                        System.out.println(cardsArray[j]);
                                    }
                                }
                            }
                            

                            【讨论】:

                            • 创建一个新的字符串数组。然后,您可以使用增强的 for 循环遍历枚举,使用枚举中的 values() 填充它。
                            【解决方案26】:

                            您不需要使用 Streams APIApache Commons 库。这里可以说是最简单和最快的方法:

                            public static String[] names() {
                                String[] names = new String[State.values().length];
                                State[] values = State.values();
                                for (int i = 0, valuesLength = values.length; i < valuesLength; i++) {
                                    names[i] = values[i].toString();
                                }
                                return names;
                            }
                            

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多