带可替换项目的键控收藏

Rob*_*d70 5 c# collections

到目前为止,我一直在使用KeyedCollection创建大型对象集合(接近一百万),每个对象都有一个uint ID字段作为集合的键。太好了,但是现在在扩展功能时遇到了一个问题:我具有“覆盖”记录,需要用新项替换具有相同键的任何现有项。平均而言,可能会覆盖20条记录中的1条,对于同一条记录,甚至可以多次重写。

我不介意在必要时从KeyedCollection进行重构。我最好的选择是什么?字典<>?这些ID不是顺序的,因此可以直接索引。

Ren*_*Pet 5

这是一个古老的问题,我以前已经利用了现有的答案。但是,在再次使用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)


Oli*_*ver 2

Dictionary您应该从集合中删除该项目一样,更改/替换它并再次添加它。