8

I using List<T> in my project, this list contains hundreds of entries. I am using List.Contains method quite a lot and this is hurting performance, I replaced the List with dictionary but it resulted in memory bottleneck, thus made performance even worst. Is there a better solution that one can suggest for searching in List? Is there a replacement of HashSet<T> in C# 2.0 or some other way that is better both memory and speed wise?

isekaijin
  • 19,076
  • 18
  • 85
  • 153
FIre Panda
  • 6,537
  • 2
  • 25
  • 38
  • What are you trying to do? What are the list constraints? You have not provided the kind of information that a recommendation needs to be based on. – Oded May 12 '11 at 12:14
  • List Iam using, and List.Contains complexity is O(N), so it is hurting performance. – FIre Panda May 12 '11 at 12:24
  • What kind of data are you holding in this list? Hundreds of entries is not that much normally. Regardless, you don't explain what you are doing with the list. Saying `Contains` means nothing. – Oded May 12 '11 at 12:26
  • Only a few hundreds? And this is causing problems? Unless you are nesting multiple loops I can't see how this would be a performance issue. – Oded May 12 '11 at 12:28
  • foreach (Entity entity in _lstEntities) { if (entitiesExt.Contains(entity.EntityId)) continue; } Profiler shows this code took 437 sec in all. – FIre Panda May 12 '11 at 12:37
  • Try this: `foreach (Entity entity in _lstEntities) { if (entitiesExt.Contains(entity)) continue; }`. You are comparing each entity to an entityId, not to another entity. – Oded May 12 '11 at 12:39
  • entitiesExt is of List not List. – FIre Panda May 12 '11 at 12:52
  • 3
    You really should be posting all of this code in your question. – Oded May 12 '11 at 12:52
  • @Abdul: If that takes 437 seconds and your list only contains hundreds of elements, there is something very wrong with your computer. – recursive May 12 '11 at 13:13
  • Hahaha, nice joke, I am talking about overall it takes 437 seconds, and that method is called thousands time. List.Contains is of O(N) in searching. – FIre Panda May 12 '11 at 14:08

3 Answers3

7

A Dictionary<T,bool> can be used in place of a HashSet<T>. Whether you add items with a value of True or False is a coin toss, the value is not relevant.

It's more cumbersome than a HashSet<T>, and not quite a light-weight, but it's certainly better than a List<T>.

Tergiver
  • 14,171
  • 3
  • 41
  • 68
3
public class HashCollection <T> : ICollection <T>
{
    private Dictionary<T, bool> _innerDictionary;

    public HashCollection()
    {
        _innerDictionary = new Dictionary<T, bool>();
    }

    void ICollection <T>.Add(T item)
    {
        AddInternal(item);
    }

    private void AddInternal(T item)
    {
        _innerDictionary.Add(item, false);
    }

    public bool Add(T item)
    {
        if (_innerDictionary.ContainsKey(item))
            return false;

        AddInternal(item);
        return true;
    }

    public void Clear()
    {
        _innerDictionary.Clear();
        _innerDictionary = new Dictionary<T, bool>();
    }

    public bool Contains(T item)
    {
        return _innerDictionary.ContainsKey(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        _innerDictionary.Keys.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return _innerDictionary.Keys.Count; }
    }

    public bool IsReadOnly
    {
        get
        {
            return false;
        }
    }

    public bool Remove(T item)
    {
        return _innerDictionary.Remove(item);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return _innerDictionary.Keys.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}
George Lica
  • 1,798
  • 1
  • 12
  • 23
2

If you can live withthe requirement that .Net 3.5 framework be installed, you can use the HashSet from .Net 3.5 (System.Core.dll) in a 2.0 project.

See this question: Using HashSet in C# 2.0, compatible with 3.5

If that's a no go, I would use dictionary instead.

Community
  • 1
  • 1
jeroenh
  • 26,362
  • 10
  • 73
  • 104