私たちのウェブアプリがUIからより限定的に実行できるものの一括操作バージョンを作成する必要があります。必要な操作は、オブジェクトをカテゴリに割り当てることです。カテゴリには複数のオブジェクトを含めることができますが、特定のオブジェクトは1つのカテゴリにのみ含めることができます。
タスクのワークフローは次のとおりです。
1)ブラウザを使用して、次の形式のファイルがアップロードされます。
# ObjectID, CategoryID
Oid1, Cid1
Oid2, Cid1
Oid3, Cid2
Oid4, Cid2
[etc.]
ファイルにはおそらく数十から数百行が含まれますが、間違いなく数千行になる可能性があります。
理想的な世界では、特定のオブジェクトIDはファイル内で1回だけ発生します(オブジェクトは1つのカテゴリにしか割り当てることができないという事実を反映しています)が、ファイルは制御外で作成されるため、実際に真であり、処理される保証はありません。その可能性に対処する必要があります。
2)サーバーはファイルを受信し、解析し、前処理して、次のようなページを表示します。
723 objects to be assigned to 126 categories
142 objects not found
42 categories not found
Do you want to continue?
[Yes] [No]
3)ユーザーがYes
ボタンをクリックすると、サーバーが実際に作業を行います。
手順(2)と(3)の両方でファイルを解析したくないので、(2)の一部として、リクエスト間で存続し、データの有用な表現を保持するコンテナを構築する必要があります。 「プレビュー」ページに入力するデータを簡単に提供して、実際の作業を効率的に実行できるようにします。(明らかにセッションはありますが、通常、メモリ内のセッション状態はほとんど保持されません。)
既存のものがあります
assignObjectsToCategory(Set<ObjectId> objectIds, CategoryId categoryId)
UIを介して割り当てが行われるときに使用される関数。単純な割り当てに加えて他の多くのビジネスロジックを実行し、この一括割り当てが実行されるときに同じビジネスロジックを実行する必要があるため、一括操作でもこのAPIを使用することが非常に望ましいです。
最初は、ファイルが特定のオブジェクトに対して「違法に」複数のカテゴリを指定した場合、ファイルが関連付けられたカテゴリの1つにオブジェクトを不意に割り当てても問題ありませんでした。
そのため、最初は、ステップ(2)でファイルを調べながら、ビルドしてクロスリクエストコンテナーに入れ
Map<CategoryId, Set<ObjectId>>
(具体的にはHashMap
、すばやく検索して挿入するために)、作業を行うときだと思っていました。マップ上で繰り返すだけで、それぞれCategoryId
に関連付けられたものを引き出して、Set<ObjectId>
に渡すことができますassignObjectsToCategory()
。
ただし、重複ObjectId
の処理方法に関する要件が変更されました。そして、それらは次のように処理されます。
- がファイル
ObjectId
に複数回出現し、すべての時間が同じに関連付けられているCategoryId
場合は、オブジェクトをそのカテゴリに割り当てます。 - がファイル
ObjectId
に複数回表示され、異なるに関連付けられてCategoryId
いる場合は、エラーと見なし、「プレビュー」ページにそのことを記載してください。
これは、ファイルから読み取ったばかりのファイルがすでにに関連付けられていることMap<CategoryId, Set<ObjectId>>
を検出するための適切な方法を提供しないため、私の戦略を台無しにしているようです。ObjectId
CategoryId
だから私の質問は、これらの重複を最も効率的に検出して追跡する方法ObjectId
ですか?
頭に浮かんだのは、「順方向」と「逆方向」の両方のマップを使用することです。
public CrossRequestContainer
{
...
Map<CategoryId, Set<ObjectId>> objectsByCategory; // HashMap
Map<ObjectId, List<CategoryId>> categoriesByObject; // HashMap
Set<ObjectId> illegalDuplicates;
...
}
次に、各(ObjectId, CategoryId)
ペアが読み込まれると、両方のマップに配置されます。ファイルが完全に読み込まれると、次のことができます。
for (Map.Entry<ObjectId, List<CategoryId>> entry : categoriesByObject.entrySet()) {
List<CategoryId> categories = entry.getValue();
if (categories.size() > 1) {
ObjectId object = entry.getKey();
if (!all_categories_are_equal(categories)) {
illegalDuplicates.add(object);
// Since this is an "illegal" duplicate I need to remove it
// from every category that it appeared with in the file.
for (CategoryId category : categories) {
objectsByCategory.get(category).remove(object);
}
}
}
}
このループが終了objectsByCategory
すると、「違法な」重複は含まれなくなり、illegalDuplicates
必要に応じて報告されるすべての「違法な」重複が含まれます。次に、繰り返して、各カテゴリobjectsByCategory
のを取得し、呼び出して割り当てを行うことができます。Set<ObjectId>
assignObjectsToCategory()
しかし、これはうまくいくと思いますが、特に入力ファイルが巨大な場合は、データを2回保存することを心配しています。また、効率性について何かが欠けているのではないかと心配しています。これは非常にゆっくりと進みます。
ダブルメモリを使用しないが、それでも迅速に実行できるこれを行う方法はありますか?ダブルメモリを使用しても、予想よりも実行速度が大幅に低下するものがありませんか?