如果ArrayList是有序的,那么ArrayList的contains()方法的工作速度是否更快?

时间:2018-07-05 07:53:34

标签: java list

我怀疑不是。如果要使用列表已排序的事实,是否应该使用二进制搜索实现自己的DateDimension方法,例如?是否有任何方法可以假设确定列表的顺序?

此问题与可能重复的问题有所不同,因为另一个问题并不询问contains()方法。

5 个答案:

答案 0 :(得分:3)

否,因为ArrayList由数组支持并且在内部按顺序搜索的indexOf(Object o)方法内部。因此排序与之无关。这是源代码:

/**
     * Returns the index of the first occurrence of the specified element
     * in this list, or -1 if this list does not contain the element.
     * More formally, returns the lowest index <tt>i</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
     */
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

答案 1 :(得分:2)

使用集合的二进制搜索来搜索有序数组列表

Collections.<T>binarySearch(List<T> list, T key)

Arraylist.contains会将其视为普通列表,并且所需时间与任何无序列表O(n)相同,而二进制搜索的复杂度在最坏情况下为O(logn)

答案 2 :(得分:2)

否。 contains使用indexOf

public boolean contains(Object var1) {
    return this.indexOf(var1) >= 0;
}

indexOf只是简单地遍历内部数组:

for(var2 = 0; var2 < this.size; ++var2) {
    if (var1.equals(this.elementData[var2])) {
        return var2;
    }
}

Collections.binarySearch是您要寻找的:

  

使用二进制文件在指定列表中搜索指定对象   搜索算法。 列表必须按升序排序   根据其元素的自然顺序(例如   sort(List)方法)之前进行此调用。如果未排序,则   结果不确定。

强调地雷

还考虑使用SortedSet之类的TreeSet,这将为元素保持正确的顺序提供更强有力的保证,而List则必须依赖调用者合同(例如上面突出显示)

答案 3 :(得分:1)

  

如果ArrayList是有序的,那么ArrayList的contains()方法是否工作更快?

不是。 ArrayList的实现不知道列表是否已排序。由于不知道,因此无法在订购时进行优化。 (检查源代码可以证明这一点。)

(假设的)基于数组的列表实现可以知道吗?我认为“否”有以下原因:

  1. 在没有Comparator或元素不能实现Comparable的要求的情况下,排序的概念是不明确的。

  2. 检查列表是否已排序的成本为O(N)。逐步检查列表是否为 顺序的开销为O(1) ...,但每次更新操作仍需要对compare进行一两次调用。对于通用数据结构而言,要在希望中优化(仅)优化API中的一个操作会产生巨大的开销。

但是没关系。如果您(程序员)能够(最好通过有效的算法手段)确保始终对列表进行排序,则可以在更新操作中使用Collections.binarySearch ...且零额外检查开销。

答案 4 :(得分:0)

只是为了简单起见。

如果您有一个数组[5,4,3,2,1]并将其排序为[1,2,3,4,5],则查找1会加快分叉的速度,但查找时间会更长5.因此,从数学的角度来看,如果您订购一个数组,无论如何要搜索内部的项都将需要从1循环到最坏的情况,即n。

也许对于您的问题排序可能有所帮助,例如您收到了无序的时间戳,但

  1. 如果您的数组不太小
  2. 想要避免对数组中每个新条目进行排序的额外费用
  3. 您只想快速找到一个对象
  4. 您知道要搜索的对象属性

您可以创建一个包含要查找的属性的KeyObject,该属性将为其实现equals&hashCode,然后将您的项存储到Map中。在任何情况下,使用Map.containsKey(new KeyObject(prop1,prop2))都比循环数组快。如果您没有真实的对象,则可以始终创建一个伪造的KeyObject,并填充您期望的属性,以检查Map。