3

虽然标题中有 Java,但这可能适用于任何 OO 语言。我想知道一些新想法来提高我正在尝试做的事情的性能。

我有一个不断接收 Object[] 数组的方法。我需要通过多个数组(列表或其他东西)拆分此数组中的对象,以便我为该方法接收的所有数组的每一列都有一个独立的列表。

例子:

List<List<Object>> column-oriented = new ArrayList<ArrayList<Object>>();

public void newObject(Object[] obj) {
    for(int i = 0; i < obj.length; i++) {
        column-oriented.get(i).add(obj[i]);
    }
}

注意:为简单起见,我省略了对象和东西的初始化。

我上面显示的代码当然很慢。我已经尝试了一些其他的东西,但想听听一些新的想法。

知道它对性能非常敏感,您将如何做到这一点?

编辑:

我测试了一些东西,发现:

我没有使用 ArrayList(或任何其他集合),而是将 Object[] 数组包装在另一个对象中以存储各个列。如果此数组达到其容量,我将创建另一个大小为两倍的数组,并使用 System.copyArray 将内容从一个复制到另一个。令人惊讶的是(至少对我来说)这比使用 ArrayList 存储内列更快......

4

4 回答 4

2

答案取决于数据和使用情况。您在此类集合中有多少数据?读/写的比例是多少(添加对象数组)?这会影响内部列表的结构更好以及许多其他可能的优化。

复制数据的最快方法是完全避免复制。如果您知道obj调用者代码没有进一步修改该数组(这是重要条件),则可能的技巧之一是实现您的自定义List类以用作内部列表。在内部,您将存储 shared List<Object[]>。每次调用我们只是将新数组添加到该列表中。自定义内部列表类将知道它代表哪一列(让它成为n),当它被要求在位置给出项目时m,它将转置mn查询内部结构以获取internalArray.get(m)[n]。这种实现是不安全的,因为对调用者的限制很容易忘记,但在某些情况下可能会更快(但是,在其他情况下可能会更慢)。

于 2010-04-29T11:14:14.487 回答
0

使用 aLinkedList来实现列列表。它随数据线性增长,为 O(1)。(如果您使用 ArrayList 它必须不时调整内部数组的大小)。

收集值后,您可以将该链表转换为数组。如果 N 是您将从为每个列表保存 3*N 引用(每个 LInkedList 具有 prevRef/nextRef/itemRef)传递到仅 N 引用的行数。

有一个数组来保存不同的列列表会很好,但是当然,这不是一个很大的改进,只有在您提前知道列数的情况下才能做到这一点。

希望能帮助到你!

编辑测试和理论表明 ArrayList 在摊销成本方面更好,即总成本除以处理的项目数量......所以不要听我的“建议”:)

于 2010-04-29T11:04:36.400 回答
0

我会尝试将 LinkedList 用于内部列表,因为它应该具有更好的插入性能。也许将 Object arra 包装到集合中并使用 addAll 也可能会有所帮助。

于 2010-04-29T11:05:44.233 回答
0

由于数组的复制,ArrayList 可能会很慢(它使用与您自己编写的集合类似的方法)。

作为替代解决方案,您可以尝试首先简单地存储行并在必要时创建列。这样,列表中内部数组的复制减少到最低限度。

例子:

//Notice: You can use a LinkedList for rows, as no index based access is used.
List<Object[]> rows =... 

List<List<Object>> columns;

public void processColumns() {
  columns = new ArrayList<List<Object>>();
  for(Object[] aRow : rows){

    while (aRow.size() > columns.size()){
      //This ensures that the ArrayList is big enough, so no copying is necessary
      List<Object> newColumn = new ArrayList<Object>(rows.size())
      columns.add(newColumn); 
    }

    for (int i = 0; i < aRow.length; i++){
      columns.get(i).add(aRow[i]);
    }
  }
}

根据列数,外部列表仍有可能在内部复制数组,但普通表包含的行数远多于列数,因此它应该只是一个小数组。

于 2010-04-29T12:12:36.217 回答