到目前为止,我一直在使用KeyedCollection创建大型对象集合(接近一百万),每个对象都有一个uint ID字段作为集合的键。太好了,但是现在在扩展功能时遇到了一个问题:我具有“覆盖”记录,需要用新项替换具有相同键的任何现有项。平均而言,可能会覆盖20条记录中的1条,对于同一条记录,甚至可以多次重写。
我不介意在必要时从KeyedCollection进行重构。我最好的选择是什么?字典<>?这些ID不是顺序的,因此可以直接索引。
这是一个古老的问题,我以前已经利用了现有的答案。但是,在再次使用KeyedCollection <>的过程中,我意识到,“删除然后添加”技术的效率不如我现在实现的技术。问题是Remove()方法线性搜索列表,然后将列表的其余部分向左移动一个条目。我在这里介绍的技术还可以线性搜索列表,但至少可以避免移动列表的其余部分。
注意 仅当替换项目与要替换的项目具有相同的密钥时才适用。
/// <summary>
/// Derived (but still abstract) version of KeyedCollection{} to provide a couple of extra
/// services, in particular AddOrReplace() and Replace() methods.
/// </summary>
public abstract class KeyedList<TKey, TItem> : KeyedCollection<TKey, TItem>
{
/// <summary>
/// Property to provide access to the "hidden" List{} in the base class.
/// </summary>
public List<TItem> BaseList
{
get { return base.Items as List<TItem>; }
}
/// <summary>
/// Method to add a new object to the collection, or to replace an existing one if there is
/// already an object with the same key in the collection.
/// </summary>
public void AddOrReplace(TItem newObject)
{
int i = GetItemIndex(newObject);
if (i != -1)
base.SetItem(i, newObject);
else
base.Add(newObject);
}
/// <summary>
/// Method to replace an existing object in the collection, i.e., an object with the same key.
/// An exception is thrown if there is no existing object with the same key.
/// </summary>
public void Replace(TItem newObject)
{
int i = GetItemIndex(newObject);
if (i != -1)
base.SetItem(i, newObject);
else
throw new Exception("Object to be replaced not found in collection.");
}
/// <summary>
/// Method to get the index into the List{} in the base collection for an item that may or may
/// not be in the collection. Returns -1 if not found.
/// </summary>
private int GetItemIndex(TItem itemToFind)
{
TKey keyToFind = GetKeyForItem(itemToFind);
return BaseList.FindIndex((TItem existingItem) =>
GetKeyForItem(existingItem).Equals(keyToFind));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1104 次 |
| 最近记录: |