Java - 在巨人列表中追加和删除的最佳策略?

时间:2013-04-17 09:51:42

标签: java performance list

使用 Java

我为一些计算等记录小物件,我只需要最后的一千个。所以我想先发布垃圾收集器。但是因为从ArrayLists中删除是昂贵的......

以下内容很重要(不能更改)

  • 没有DB
  • 对象类型相同
  • 每秒最多50,000个对象
  • 性能重要
  • 快速遍历整个列表非常重要
  • 随机访问也很重要

这可以改变:

  • 现在使用ArrayList<MyObject>
  • 限制:100,000个对象(停止录制,但必须继续)

我的猜测:

  • 链表
  • RingBuffer
  • ???

我可以做些什么来快速迭代并同时快速发布旧对象?

3 个答案:

答案 0 :(得分:5)

解决方案

... 如果您需要一定数量的最后元素,只需使用数组作为环形缓冲区的基础。

  • 单一分配

  • 没有得到/放/等。内联方法开销

  • 简单的

示例(可能无法编译,即时编写)实现:

class LastElementsStore<T> {
  Object[] arr;
  int size;
  int nextPutIndex;

  LastElementsStore(int size ) {
    arr = new Object[size];
    this.size = size;
  }

  void put(T elt) {
    arr[nextPutIndex] = elt;
    nextPutIndex++;
    if (nextPutIndex == size) {
      nextPutIndex = 0;
    }
  }

  // getters of your choice

}

如果没有足够的元素,将返回空值。

如果你需要它们,你可以从nextPutIndex开始,一直读到最后,然后转到0并继续阅读。

您可以完全控制内存,不会像在LinkedList中那样进行额外的节点分配,也不会像在ArrayList中那样调整大小。

只要达到限制,旧对象就会自动释放

您的要求

  • 没有DB完成,只使用了一个数组

  • 对象属于同一类型 - 简单模板

  • 每秒最多50,000个对象 - 如果数组无法处理它,Java中没有任何东西

  • 性能很重要 - 如上所述,访问数组没有额外的开销 快速迭代整个列表非常重要 - 尽可能快地迭代

  • 随机访问也很重要 - 数据是有序的,nextPutIndex之后的第一个非空元素是第一个可用的

答案 1 :(得分:3)

在不了解任何其他要求的情况下,某些类型的链接列表似乎是合适的。只需跟踪第一个元素(列表中的“头部”)和最后一个元素(“尾部”)。每个链接的元素都会重新引用下一个元素添加到尾部,并从头部移除。

添加和删除速度非常快(O(1)),迭代也很简单。

但是,如果您需要随机访问元素,那么此解决方案的效果会很差。

修改

由于您已添加了需要随机访问的权限,因此链接列表将无效。如果修复了任何给定时间的最大对象数,则可以使用ArrayList(或基本Java数组)并将其视为环绕缓冲区。到达最后,从头开始替换对象,并跟踪表示列表逻辑起点的索引。 (如果使用基本数组,则还需要跟踪缓冲区中当前有多少元素 - 相当于List.size())。

当您在缓冲区的开头替换对象时,旧对象将自动释放并进行垃圾收集(只要它们未在别处引用)。

答案 2 :(得分:3)

我会使用一个数组,并实现一个RingBuffer。 我已经这样做了,但是使用了很多单元测试来确保它始终有效。 我没有找到适合我需要的环形缓冲区,也许你有更多的运气。