본문 바로가기

C#

BigList 모델 구현

728x90

BigList를 구현하게 된 건 list의 크기가 커서 발생하는 Out Of Memory를 줄이기 위함이었다. 출처에서의 파일은 vb여서 이를 컨버트하는 작업을 했봤다. 맞는지는 모름..

public class BigList<T> : IEnumerator<T>, IEnumerable<T>
{
    private List<List<T>> _listOfLists;
    private Int64 _enumIndex = -1;
    private int _listIndex = 0;
    private T _current;

    public BigList()
    {
        _listOfLists = new List<List<T>>();
        _listOfLists.Add(new List<T>());
        _enumIndex = -1;
        _listIndex = 0;
    }

    public T this[long index]
    {
        get
        {
            var li = 0;
            var ti = 0;
            GetSubIndexes(index, ref li, ref ti);
            return _listOfLists[li][ti];
        }
        set
        {
            var li = 0;
            var ti = 0;
            GetSubIndexes(index, ref li, ref ti);
            _listOfLists[li][ti] = value;
        }
    }

    public int MaxItemsPerSublist = 500000;

    public T Current
    {
        get
        {
            int li = 0;
            int ti = 0;
            GetSubIndexes(_enumIndex, ref li, ref ti);
            _current = _listOfLists[li][ti];
            return _current;
        }
    }

    object IEnumerator.Current => Current;

    public Int64 Count()
    {
        var sum = 0;
        foreach (var i in _listOfLists)
        {
            sum += i.Count;
        }

        return sum;
    }

    public Int64 Add(T item)
    {
        _listOfLists[_listIndex].Add(item);

        if (_listOfLists[_listIndex].Count == this.MaxItemsPerSublist)
        {
            _listOfLists.Add(new List<T>());
            _listIndex += 1;
        }

        return this.Count();
    }

    public bool Remove(T item)
    {
        int index;

        for (int i = 0; i < _listIndex; i++)
        {
            index = _listOfLists[i].IndexOf(item);
            if (index > -1)
            {
                _listOfLists[i].RemoveAt(index);
                return true;
            }
        }

        return false;
    }

    public Int64 IndexOf(T item)
    {
        int index;
        for (int i = 0; i < _listIndex; i++)
        {
            index = _listOfLists[i].IndexOf(item);
            if (index > -1)
                return (1 * MaxItemsPerSublist) + index;
        }

        return -1;
    }

    public bool Clear()
    {
        foreach (var i in _listOfLists)
            i.Clear();
        _listOfLists.Clear();
        _listOfLists = new List<List<T>>();
        _listOfLists.Add(new List<T>());
        _enumIndex = -1;
        _listIndex = 0;

        return true;
    }

    public IEnumerator<T> GetEnumerator() => this;

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

    public bool MoveNext()
    {
        if (_enumIndex < this.Count() - 1)
        {
            _enumIndex += 1;
            return true;
        }
        else
        {
            Reset();
            return false;
        }
    }

    public void Reset()
    {
        _enumIndex = -1;
    }

    public void Dispose()
    {
        //throw new NotImplementedException();
    }

    private bool GetSubIndexes(Int64 index, ref int listIndex, ref int itemIndex)
    {
        var li = 0;
        var ri = 0;
        var nid = index;
        var sum = 0;
        var indexFound = false;

        for (int i = 0; i < _listIndex; i++)
        {
            if (index < sum + _listOfLists[i].Count)
            {
                listIndex = li;
                itemIndex = Convert.ToInt32(index - sum);
                indexFound = true;
                break;
            }
            else
            {
                li += 1;
                sum += _listOfLists[i].Count;
            }
        }

        if (!indexFound)
            return false;
        return true;
    }
}

 

[출처]
https://www.codeproject.com/Tips/1071827/Avoid-Out-of-memory-Troubles-with-Very-Large-Lists

728x90