更快的ArrayList访问版本?

时间:2017-04-06 10:20:01

标签: java multithreading arraylist large-data-volumes

有没有人知道类似于ArrayList的东西,它更适合尽可能快地处理大量数据?

我有一个程序,它有一个非常大的ArrayList,当它试图探索或修改ArrayList时会被阻塞。

大概是你做的时候:

//i is an int;
arrayList.remove(i);

幕后代码运行如下:

public T remove(int i){
    //Let's say ArrayList stores it's data in a T [] array called "contents".
    T output = contents[i];
    T [] overwrite = new T [contents.length - 1];
    //Yes, I know generic arrays aren't created this simply. Bear with me here...
    for(int x=0;x<i;x++){
        overwrite[x] = contents[x];
    }
    for(int x=i+1;x<contents.length;x++){
        overwrite[x-1] = contents[x];
    }
    contents = overwrite;
    return output;
}

当ArrayList的大小为几百万左右时,重新排列数组中项目位置的所有周期将花费大量时间。

我试图通过创建我自己的自定义ArrayList子类来解决这个问题,该子类将它的数据存储划分为更小的ArrayLists。任何需要ArrayList扫描特定项目数据的进程都会为每个较小的ArrayLists生成一个新的搜索线程(以利用我的多个CPU核心)。

但是这个系统不起作用,因为当调用搜索的线程在任何ArrayLists中同步一个项时,它可以阻止那些单独的搜索线程完成搜索,从而锁定原始线程在这个过程中称为搜索,基本上使整个程序陷入僵局。

我真的需要某种数据存储类,以便能够像PC一样快速地包含和操作大量对象。

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

  

我真的需要某种数据存储类,以便能够像PC一样快速地包含和操作大量对象。

答案很大程度上取决于您所谈论的数据类型以及您需要的具体操作。你使用的工作&#34;探索&#34;没有定义它。

如果您正在讨论查找记录,那么对于线程操作,没有什么比HashMap - ConcurrentHashMap更好。如果你在谈论保持秩序,特别是在处理线程时,那么我建议ConcurrentSkipListMap具有O(logN)查找,插入,删除等。

您可能还想考虑使用多个集合。您需要注意,集合不会失去同步,这对于线程来说尤其具有挑战性,但根据您正在进行的各种操作,这可能会更快。

  

当ArrayList的大小为几百万左右时,重新排列数组中项目位置的所有周期将花费大量时间。

如上所述,ConcurrentSkipListMap是O(logN),用于重新排列项目。即删除并添加新职位。

  

幕后的[ArrayList.remove(i)]代码运行如下:......

嗯,不是真的。你可以看一下code in the JDK吧? ArrayList使用System.arraycopy(...)进行此类操作。它们可能对你的情况没有效率,但它不是O(N)

答案 1 :(得分:0)

链接列表的良好用法的一个示例是列表元素非常大,即。足够大,只有一两个可以同时适应CPU缓存。此时,用于迭代的连续块容器(如矢量或数组)的优势或多或少地无效,并且如果实时发生许多插入和移除,则可能具有性能优势。

参考:Under what circumstances are linked lists useful?

参考:https://coderanch.com/t/508171/java/Collection-datastructure-large-data

答案 2 :(得分:0)

不同的集合类型对于各种操作具有不同的时间复杂度。典型的复杂性是:O(1),O(N)和O(log(N))。要选择集合,首先需要确定经常使用的操作,并避免对该操作具有O(N)复杂性的集合。在这里,您经常使用操作ArrayList.remove(i),即O(N)。更糟糕的是,您使用remove(i)而非remove(element)。如果remove(element)是唯一经常使用的操作,则LinkedList可以提供帮助,其remove(element)为O(1),但LinkedList.remove(i)也为O(N)。< / p>

我怀疑可以实现List具有remove(i)复杂度的O(1)。最好的时间是O(log(N)),这肯定比O(N)好。 Java标准库没有这样的实现。您可以尝试通过“二进制索引树”关键字进行谷歌搜索。

但我要做的第一件事就是检查算法并尝试摆脱List.remove(i)操作。