예제 #1
0
        /// <summary>
        /// Gets a list containing all the keys in the collection.
        /// </summary>
        /// <returns>Returns all keys stored in <see cref="_table"/></returns>
        public List <TKey> GetKeys()
        {
            var keys = new List <TKey>();

            foreach (var node in _table)
            {
                MapperNode <TKey, TValue> current = node;
                while (current != null)
                {
                    keys.Add(current._key);
                    current = current._next;
                }
            }

            return(keys);
        }
예제 #2
0
        /// <summary>
        /// Double number of indices for each key properties.
        /// Increase <see cref="_table"/> capacity 2^KeySize times
        /// </summary>
        private void ExpandTable()
        {
            var newSize          = 0;
            var newNonEmptyNodes = 0;
            var newRangePerKey   = _rangePerKey * 2;
            var newTable         = new MapperNode <TKey, TValue> [newRangePerKey.Pow(KeySize)];

            lock (_table)
            {
                for (int i = 0; i < _table.Length; i++)
                {
                    MapperNode <TKey, TValue> current = _table[i];
                    while (current != null)
                    {
                        var index = HashesToTableIndex(current._hashes, newRangePerKey);

                        if (newTable[index] == null)
                        {
                            newTable[index] =
                                new MapperNode <TKey, TValue>(current._key, current._value, current._hashes, null);
                            newNonEmptyNodes++;
                            newSize++;
                        }
                        else
                        {
                            newTable[index].Add(current._key, current._value, current._hashes, out var added);
                            newSize += added;
                        }

                        current = current._next;
                    }
                }

                _rangePerKey = newRangePerKey;
                _table       = newTable;

                NonEmptyNodes = newNonEmptyNodes;
                Size          = newSize;
            }
        }
예제 #3
0
        /// <summary>
        /// Indexer, which allows to get and also set values of a collection by a key.
        /// </summary>
        /// <param name="key">Received key value</param>
        /// <exception cref="ArgumentNullException"></exception>
        public TValue this[TKey key]
        {
            set
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                if (value == null)
                {
                    throw new ArgumentNullException(nameof(value));
                }

                lock (_keys) _keys.Add(key); // should contain unique values but cause performance

                if (NonEmptyNodes == Capacity)
                {
                    ExpandTable();
                }

                var hashes = HashesOfKey(key);
                var index  = HashesToTableIndex(hashes, _rangePerKey);

                if (_table[index] == null)
                {
                    _table[index] = new MapperNode <TKey, TValue>(key, value, hashes, null);
                    NonEmptyNodes++;
                    Size++;
                }
                else
                {
                    lock (_table[index])
                    {
                        _table[index].Add(key, value, hashes, out var added);
                        Size += added;
                    }
                }
            }
            get
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }

                var index = KeyToTableIndex(key, _rangePerKey);
                var node  = _table[index];
                while (node != null)
                {
                    MapperNode <TKey, TValue> next;
                    lock (node)
                    {
                        if (IsKeysEqual(node._key, key))
                        {
                            return(node._value);
                        }

                        next = node._next;
                    }
                    node = next;
                }

                return(default(TValue));
            }
        }