Arrays.asList().contains() 的性能与多个 if equals 指令相比如何?

4
以下哪条指令在性能和内存使用方面更好:
if(val.equals(CONSTANT1) || val.equals(CONSTANT2) ..... || val.equals(CONSTANTn)) {

}

或者

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

}

1
常量1、常量2的类型是什么? - Achintya Jha
2
你为什么想这样做?为什么不使用Set? - Christophe Roussy
我正在使用PMD来检查代码的复杂性,如果代码里有一系列if/equals语句,就意味着它具有很高的代码复杂性。然而,使用Arrays.asList().contains()版本则不会如此。 - user2086656
4个回答

2
更好的问题应该是如何更清晰地编写此代码(如果性能确实很重要,则还需更快)。答案是使用switch语句(或甚至多态,如果您想将常量转换为枚举)或查找数组。但如果您坚持比较两种方法,则第一种方法略快。为了证明这一点,让我们看看第二种方法包含哪些步骤:
1.创建一个新的带有常量的数组,以将它们传递给Arrays.asList的可变参数参数。 2.创建一个包装该数组的新列表对象。 3.遍历该数组,将每个元素与equals进行比较。
第三步等同于您的第一种方法。最后值得注意的是,这样的操作很可能少于一微秒,因此除非您每秒调用此方法数百万次,否则任何方法都足够快。

2
理论上,#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;
}

1

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

然而,话虽如此,如果一个人手动迭代并使用equals()与asList()和contains()......仍然是一样的。

Arrays.asList()返回一个私有的列表实现,它扩展了AbstractList,并通过引用简单地包装现有数组(不进行复制)。contains()方法使用indexOf(),它在每个元素上使用equals()遍历数组,直到找到匹配项,然后返回它。如果您在找到equals时中断循环,则两种实现将非常相似。

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


我正在使用以下版本: if(Arrays.asList(CONSTANT1,CONSTANT2, ..... ,CONSTANTn).contains(val)) { } 因为PMD指出if/equals版本的代码复杂度较高。 - user2086656
没问题。此外,考虑到两种实现完全等效,我会选择使用asList() + contains()方法,这是最简洁的方法了。 - Francisco Paulo

0

如果(val.equals(CONSTANT1) || val.equals(CONSTANT2) ..... || val.equals(CONSTANTn)) {

}

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接