Java 更快的ArrayList访问版本?

Java 更快的ArrayList访问版本?,java,multithreading,arraylist,large-data-volumes,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".

有没有人知道类似于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子类来缓解这个问题,该子类将数据存储分割成更小的ArrayList。任何需要ArrayList扫描其数据以查找特定项的进程都会为其中每个较小的ArrayList生成一个新的搜索线程,以利用我的多个CPU核

但是这个系统不起作用,因为当调用搜索的线程在任何ArrayList中同步了一个项目时,它会阻止那些单独的搜索线程完成搜索,这反过来又会锁定在进程中调用搜索的原始线程,基本上会使整个程序死锁

我真的需要某种面向数据存储的类,能够以PC机所能达到的速度容纳和操作大量对象


有什么想法吗?

链表的一个好用法是,链表元素非常大,即足够大,只有一个或两个可以同时放入CPU缓存。在这一点上,相邻块容器(如用于迭代的向量或数组)的优势或多或少是无效的,如果实时发生许多插入和删除,则性能优势可能是可能的

参考:


参考:

不同的收集类型对于不同的操作具有不同的时间复杂度。典型的复杂性是:O1、ON和OlogN。要选择集合,首先需要确定经常使用的操作,并避免集合对该操作的复杂性产生影响。在这里,您经常使用启用的操作ArrayList.removei。更糟糕的是,您使用removei而不是removeelement。如果removeelement是唯一经常使用的操作,那么LinkedList可能会有所帮助,它的removeelement为O1,但LinkedList.RemoveId也处于启用状态

我怀疑removei复杂性为O1的列表能否实现。最好的时间是OlogN,它肯定比ON好。Java标准库没有这样的实现。你可以试着用二叉索引的树关键字来搜索它

但我要做的第一件事是检查算法并尝试摆脱List.removei操作

我真的需要某种面向数据存储的类,能够以PC机所能达到的速度容纳和操作大量对象

答案在很大程度上取决于您所谈论的数据类型以及您需要的具体操作。您使用work explore而不定义它

如果您谈论的是查找记录,那么没有什么比HashMap更好的了——线程操作的ConcurrentHashMap。如果您谈论的是保持秩序,特别是在处理线程时,那么我建议使用ConcurrentSkipListMap,它具有OlogN查找、插入、删除等功能

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

当ArrayList的大小大约为几百万个单位时,所有这些重新排列数组中项目位置的循环将花费大量时间

如前所述,ConcurrentSkipListMap是用于重新排列项目的OlogN。i、 e.移除并添加新位置

[ArrayList.removei]代码在后台运行如下内容:


嗯,不是真的。你能看看右边吗?ArrayList使用System.arraycopy。。。对于这些类型的操作。它们可能对您的案例无效,但未启用。

尝试使用LinkedList阵列如何?当然,它需要一些帮助函数。我会使用ConcurrentLinkedHashMapI,我倾向于使用DUP来关闭。。。但就目前而言:请检查该页面是否提供了继续操作所需的信息。与您的假设相反,ArrayList.remove实现通常只执行System.arrayCopy,从i+1..end到i..end-1。他们不分配任何额外的空间。请记住,ArrayList的支持数组通常大于ArrayList的大小。System.arrayCopy通常是本机代码,速度非常快。您确定是remove方法占用了CPU时间吗?在Java中,没有包含大型元素的数组或ArrayList。最大的元素可能是一个长的或64位的指针/引用。我和他关心的是列表中没有元素,而不是每个元素的大小w
嗯,我使用的元素主要是自定义对象,它们最终包含大约60个浮点数,可能还有十几个整数。这些数字中的大多数实际上都包含在其中的其他自定义对象中。因此,如果只使用ArrayList.removeArrayList.geti,而不是ArrayList.removei,我的性能会更好吗?@Cambot当然不会。ArrayList.removeobject与ArrayList.removei-ON一样慢,事实上甚至更慢。是的,我认为这可能不会让事情变得更好,因为如果它真的这样做了,Java用户肯定会重新编码ArrayList来实现这一点。顺序很重要,所以听起来我需要ConcurrantSkipListMap。在这种情况下,我如何用这个类复制opperation ArrayList.addint对象?这是ArrayList的一个方面,我的程序使用了一个相当大的位,因此任何替换都需要能够执行类似的函数。当然,您可以使用该int作为对象@Cambot的键。因此,您将删除对象,然后使用新对象对对象进行putint。还可以将int as字段添加到对象中。如果您不控制对象,那么您可以创建一个包装器对象来处理hashCode和equals方法。