3

タイトルに Java が含まれていますが、これはどのオブジェクト指向言語にも当てはまります。やろうとしていることのパフォーマンスを向上させるための新しいアイデアをいくつか知りたいです。

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[] 配列を別のオブジェクトでラップして、個々の列を格納しました。この配列が容量に達した場合は、サイズが 2 倍の別の配列を作成し、System.copyArray を使用して内容をある配列から別の配列にコピーします。驚くべきことに(少なくとも私にとっては)、ArrayListを使用して内部列を格納するよりも高速です...

4

4 に答える 4

2

答えは、データと使用プロファイルによって異なります。そのようなコレクションにはどれくらいのデータがありますか? 読み取り/書き込みの割合はどのくらいですか (オブジェクト配列を追加)? これは、内部リストのどの構造が優れているか、および他の多くの可能な最適化に影響します。

データをコピーする最速の方法は、コピーをまったく行わないことです。配列が呼び出し元のコードによってそれ以上変更されないことがわかっている場合(これは重要な条件です)、考えられるトリックの 1 つは、内部リストとして使用するobjカスタム クラスを実装することです。List内部的には shared を保存しList<Object[]>ます。呼び出すたびに、そのリストに新しい配列を追加するだけです。カスタムの内部リスト クラスは、それが表す列を認識し ( としますn)、 item の位置を指定するように求められると、m転置mn、内部構造を照会して を取得しますinternalArray.get(m)[n]。この実装は、忘れやすい呼び出し元の制限により安全ではありませんが、特定の条件下では高速になる可能性があります (ただし、他の条件下では低速になる可能性があります)。

于 2010-04-29T11:14:14.487 に答える
0

LinkedList列リストの実装にはa を使用します。それはデータとともに直線的に成長し、O(1) です。(ArrayList を使用する場合は、内部配列のサイズを時々変更する必要があります)。

値を収集した後、そのリンク リストを配列に変換できます。N が各リスト (各 LInkedList には prevRef/nextRef/itemRef がある) の 3*N ref の保持から N ref のみに渡される行数である場合。

さまざまな列リストを保持するための配列があると便利ですが、もちろん、それは大きな改善ではなく、列数が事前にわかっている場合にのみ実行できます。

それが役に立てば幸い!

編集テストと理論は、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 に答える