代码之家  ›  专栏  ›  技术社区  ›  Asaf

当使用enum.values()与字符串数组时,性能是否受到影响?

  •  17
  • Asaf  · 技术社区  · 16 年前

    我用枚举替换 String Java应用程序中的常量(JRE 1.5)。

    当我将枚举作为一个方法中的静态名称数组来处理时(例如在呈现ui时),是否会影响性能?

    我的代码看起来有点像这样:

    public String getValue(int col) {
      return ColumnValues.values()[col].toString();
    }
    

    澄清:

    • 我担心的是与列举有关的隐藏成本 values() 重复(例如,在paint()方法中)。
    • 我现在可以看到我的所有场景包括 int = & gt; enum 转换-这不是Java的方式。

    提取的实际价格是多少 值() 数组?这是个问题吗?

    安卓开发者

    阅读下面西蒙·兰霍夫的答案,这是早前极客们在接受答案的评论中所指出的拥抱。 Enum.values() 必须做一个防御性的拷贝

    7 回复  |  直到 8 年前
        1
  •  16
  •   Joe Carnahan    16 年前

    Enum.values() 提供对数组的引用,对枚举数组进行迭代的成本与对字符串数组进行迭代的成本相同。同时,将枚举值与其他枚举值进行比较实际上可以是 更快 把字符串和字符串进行比较。

    同时,如果您担心调用 values() 方法与已经拥有对数组的引用相比,不用担心。Java中的方法调用(现在)非常快,并且在任何时候它对性能都很重要,无论如何,方法调用都会被编译器内联。

    所以,说真的, 别担心。 而是集中于代码的可读性,并使用 Enum 这样,如果您试图使用代码不希望处理的常量值,编译器将捕获它。


    如果您想知道为什么枚举比较可能比字符串比较快,那么下面是详细信息:

    这取决于弦是否 interned 或者没有。为了 枚举 对象,系统中每个枚举值始终只有一个实例,因此每次调用 Enum.equals() 可以很快完成,就像您使用 == 运算符而不是 equals() 方法。事实上, 枚举 物品,使用安全 = 而不是 等式() ,而那是 不 用绳子做是安全的。

    对于字符串,如果字符串已被实习,则比较速度与 枚举 . 但是,如果这些线没有被拘留,那么 String.equals() 方法实际上需要遍历两个字符串中的字符列表,直到其中一个字符串结束或发现两个字符串之间不同的字符为止。

    但是,这可能并不重要,即使在必须快速执行的swing呈现代码中也是如此。-)


    @本林斯指出 枚举值() 必须执行防御复制,因为数组是可变的,您可以替换数组中由 枚举值() . 这意味着你必须考虑到这一防御副本的成本。但是,复制单个连续数组通常是一个快速操作,假设它是使用某种内存复制调用“在幕后”实现的,而不是简单地迭代数组中的元素。所以,我认为这不会改变最后的答案。

        2
  •  14
  •   Simon Langhoff    11 年前

    对于枚举,为了保持不变性,它们会在每次调用values()方法时克隆后备数组。这意味着它将对性能产生影响。多少取决于你的具体情况。

    我一直在监控自己的android应用程序,发现这个简单的调用 13.4% CPU time! 就我的具体情况而言。

    为了避免克隆values数组,我决定将这些值简单地缓存为私有字段,然后在需要时循环遍历这些值:

    private final static Protocol[] values = Protocol.values();
    

    经过这个小小的优化之后,我的方法调用只占用了一个微不足道的 0.0% CPU time

    在我的用例中,这是一个受欢迎的优化,但是,需要注意的是,使用这种方法是对枚举的可变性的权衡。谁知道一旦你给人们一个参考,他们会把什么放进你的价值观数组中呢!?

        3
  •  2
  •   Riduidel    16 年前

    作为经验法则:在考虑优化之前,您是否知道这段代码可能会减慢应用程序的速度?

    现在,事实。

    枚举在很大程度上是散布在编译过程中的语法糖。因此,为枚举类定义的values方法返回一个静态集合(也就是说,在类初始化时加载),其性能可以被认为大致等同于数组1。

        4
  •  2
  •   Aaron Digulla    16 年前

    如果你关心的是表现,那么衡量一下。

    从代码来看,我不希望有任何意外,但90%的性能猜测是错误的。如果希望安全,请考虑将枚举上移到调用代码中(即 public String getValue(ColumnValues value) {return value.toString();} )

        5
  •  2
  •   Chameleon    9 年前

    使用此:

    private enum ModelObject { NODE, SCENE, INSTANCE, URL_TO_FILE, URL_TO_MODEL,
        ANIMATION_INTERPOLATION, ANIMATION_EVENT, ANIMATION_CLIP, SAMPLER, IMAGE_EMPTY,
        BATCH, COMMAND, SHADER, PARAM, SKIN }
    private static final ModelObject int2ModelObject[] = ModelObject.values();
    
        6
  •  1
  •   jdoe7777777    8 年前

    如果迭代枚举值只是为了查找特定值,则可以静态地将枚举值映射为整数。这将推送对类负载的性能影响,并使基于映射参数获取特定枚举值变得简单/低影响。

    public enum ExampleEnum {
        value1(1),
        value2(2),
        valueUndefined(Integer.MAX_VALUE);
    
        private final int enumValue;
        private static Map enumMap;
        ExampleEnum(int value){
           enumValue = value;
        }
        static {
           enumMap = new HashMap<Integer, ExampleEnum>();
           for (ExampleEnum exampleEnum: ExampleEnum.values()) {
               enumMap.put(exampleEnum.value, exampleEnum);
            }
        }
        public static ExampleEnum getExampleEnum(int value) {
            return enumMap.contains(value) ? enumMap.get(value) : valueUndefined;
        }
    }
    
        7
  •  -1
  •   Artsiom Anisimau    16 年前

    我想是的。使用常数更方便。