1

非常に柔軟性のないソケット API に接続しています。次のような行が返されます。

NAME, CITY, STATE, JOB, MONTH

ただし、集計を行わないため、重複があります。重複行をカウントする必要があります (これは SQL では非常に簡単ですが、私の知る限り、Java ではそうではありません)。

ソース データの例:

NAME,     CITY, STATE, JOB,         MONTH
John Doe, Denver, CO, INSTALLATION, 090301
John Doe, Denver, CO, INSTALLATION, 090301
John Doe, Denver, CO, INSTALLATION, 090301
Jane Doe, Phoenix, AZ, SUPPORT, 090301

意図されました:

    NAME,    CITY, STATE,          JOB,  MONTH, COUNT
John Doe,  Denver,    CO, INSTALLATION, 090301,   3
Jane Doe, Phoenix,    AZ,      SUPPORT, 090301,   1

約 100,000 の戻り行に対してこれを簡単に実行できますが、1 か月で約 6,000 万行を処理しています。何か案は?

編集: 残念ながら、行はソートされて返されません...また、API を介してソートするオプションもありません。集約する必要のあるこの巨大な混乱があります。現在、ArrayList を使用して indexOf(new row) を実行して、アイテムが既に存在するかどうかを確認していますが、行が増えるほど遅くなります。

編集:明確にするために、これは月末に月に一度だけ実行する必要があります。すべての応答に感謝します

4

5 に答える 5

3

HashSetを使用して、同じ内容の前の行を格納できます。(Rowオブジェクトに適切な.hashValue()および.equals()メソッドが実装されていると仮定します。

おそらくこのようなもの:

Set<Row> previousRows = new HashSet<Row>();
List<Row> rowsInOrder = new LinkedList<Row>();

次に使用中(さらに、RowクラスへのincrementCount()メソッドがあると仮定します):

Row newRow = getNextRow();
if(!previousRows.contains(newRow)){
    previousRows.put(newRow);
    rowsInOrder.add(newRow);
} 
previousRows.get(newRow).incrementCount();

行が入ってくる順序を気にしない場合は、リストを削除してセットを使用することができます。

于 2009-11-07T04:23:22.400 に答える
1

すべてのデータを一度にメモリに収めることができますか?あなたがそれをArrayListに入れているなら、それはあなたができるように聞こえます。

その場合は、GoogleコレクションにあるようなMultiSetの実装を使用できます。

次に、次のようにすべての行をマルチセットに挿入することができます

Multiset<Row> rowMultiset = HashMultiset.create();
for (Row row: rows) {
  rowMultiset.add(row);
}

そして、次のようなものを使用して、カウントを繰り返して繰り返すことができます。

for (Multiset.Entry entry : rowMultiset.entrySet()) {
  System.out.println("row: "+entry.getElement()+", count: "+entry.getCount());
}

外部ライブラリを使用したくない場合は、行を整数にマッピングするHashMapを使用して同様のことを行うことができます。

すべての行がメモリに収まらない場合、最も簡単なアプローチは、データをデータベースに挿入してクエリを実行することだと思います。データベースは、メモリに収まらない大規模なデータセット用に設計および最適化されています。

于 2009-11-07T04:25:28.263 に答える
1

柔軟性がありますか、それともHadoopのようなものに投資するのに十分なほど重要なタスクですか? そのサイズのデータ​​では、「マップ削減」の考え方の観点から検討を開始する必要があります。

于 2009-11-07T03:32:20.147 に答える
0

行は常にソートされて返されますか?すなわち。グループ化される行は常に次々に返されますか?答えが「はい」の場合:

1)カウンターを初期化します。

2)読んだばかりの前の行を追跡し、現在の行と比較します。それが同じである場合、あなたのカウンターを増やします。異なる場合は、現在のカウンター値を使用して行を記録し、カウンターをリセットします。

3)最後のレコードに到達したら、必ず現在のカウントで行を記録してください。

この戦略により、ストリーム内の大きなデータセットを読み込み、プログラムのメモリフットプリントを低く抑えながら、必要なよりコンパクトな集合データを生成できます。

于 2009-11-07T03:35:06.070 に答える
0

これを行うには、次の 4 つの方法が考えられます。

  • メモリ内に 6,000 万行の表現を保持するのに十分なメモリがある (重複が少ない) 場合は、a を使用しHashMap<Row, Integer>てカウントを表します。

  • 行を RDB に格納し、SQL を使用して集計とカウントを行います。

  • 行を大きなファイルに書き込み、単一のパスで行をカウントする前に、従来のマージ ソートを使用します。

  • Hadoop などを使用して、行を複数のマシンに分散させます。

1 か月以上の期間にわたってカウントが蓄積されることが予想されるという事実は、アプリケーションの再起動が必要になる可能性を考慮する必要があることを示唆しています。これは、RDB またはファイルベースのソリューションが必要であることを示唆しています。

于 2009-11-07T08:39:59.403 に答える