【问题标题】:Performance of Arrays.asList().contains() comparing to several if equals instructionsArrays.asList().contains() 与多个 if equals 指令的性能比较
【发布时间】:2013-02-04 00:17:20
【问题描述】:

这些说明中哪个在性能和内存使用方面更好:

if(val.equals(CONSTANT1) || val.equals(CONSTANT2) ..... || val.equals(CONSTANTn)) {

}

if(Arrays.asList(CONSTANT1,CONSTANT2, ..... ,CONSTANTn).contains(val)) {

}

【问题讨论】:

  • CONSTANT1 CONSTANT2...的类型是什么?
  • 你为什么要这样做?为什么不使用 Set ?
  • 我正在使用 PMD 来检查代码的复杂性,并且有一系列 if / equals 语句表明代码复杂性很高,而使用 Arrays.asList().contains() 版本则不会

标签: java arrays if-statement


【解决方案1】:

理论上#1 更快但无关紧要,因为 Arrays.asList 只创建一个对象 - 指定数组的列表视图(包装器),没有数组复制:

public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a);
}

private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
    private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;

ArrayList(E[] array) {
        if (array==null)
            throw new NullPointerException();
    a = array;
}

【讨论】:

    【解决方案2】:

    一个更好的问题是如何更清楚地编写此代码(如果性能确实很重要,则速度更快)。答案是switch 语句(或者甚至可能是多态性,如果您想将常量转换为枚举)或查找数组。

    但如果你坚持比较你的两种方法,第一种会稍微快一些。要了解这一点,让我们看一下第二种方法的含义:

    1. 使用常量创建一个新数组,将它们传递给 Arrays.asList 的 vararg 参数
    2. 创建一个包装该数组的新列表对象
    3. 遍历该数组,将每个元素与等号进行比较

    第三步相当于你的第一步。

    最后,值得注意的是,这样的操作可能需要不到一微秒的时间,因此除非您每秒调用此方法数百万次,否则任何方法都足够快。

    【讨论】:

      【解决方案3】:

      由于您没有使用循环,我猜值的数量非常少,以至于实际上任何差异都无关紧要。

      但是,话虽如此,如果要手动迭代并使用 equals() 与 asList() 和 contains() ......它仍然是相同的。

      Arrays.asList() 返回一个列表的私有实现,它扩展了 AbstractList 并通过引用简单地环绕现有数组(不进行复制)。 contains() 方法使用 indexOf() 对每个元素使用 equals() 遍历数组,直到找到匹配项然后返回它。如果你在找到一个 equals 时打破你的循环,那么这两个实现将是完全等价的。

      唯一的区别是 Arrays.asList() 创建的附加列表结构的内存占用很小,除此之外...

      【讨论】:

      • 我正在使用这个版本: if(Arrays.asList(CONSTANT1,CONSTANT2, ..... ,CONSTANTn).contains(val)) { } 因为 PMD 说 if /equals 版本有代码复杂度高
      • 是的,没问题。此外,鉴于这两种实现是完全等价的,我会选择 asList() + contains() 方法,你不会比这更干净。
      【解决方案4】:

      if(val.equals(CONSTANT1) || val.equals(CONSTANT2) ..... || val.equals(CONSTANTn)) {

      }

      在性能和内存方面更好,因为第二个需要时间来构建一个列表并开始在该列表中搜索 val。这里需要额外的内存来维护列表,并且需要额外的时间来遍历列表。其中将 val 与常量进行比较将使用短路比较方法。

      【讨论】:

        猜你喜欢
        • 2020-05-28
        • 2020-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-05
        相关资源
        最近更新 更多