public void store(K key, V value) {
        int hash = key.hashCode();
        int index = indexOf(key, hash);
        
        if (table[index] == null) {
            // bucket is empty -> the key does not exist -> create a new Entry
            Entry<K, V> newEntry = new Entry<K, V>(key, value, hash, null);
            table[index] = newEntry;
            Queue.Node<LruEntry> lruElem = lru.insert(new LruEntry(index, newEntry));
            newEntry.queueEntry = lruElem;
        } else {
            Entry<K, V> entry = table[index];
            // first, search for the key in the bucket. If found change the value
            boolean found = false;
            while (entry != null && !found) {
                if (isKey(key, hash, entry)) {
                    entry.value = value;
                    lru.moveBack(entry.queueEntry); // we just accessed the entry
                    found = true;
                }
                entry = entry.next;
            }
            
            // key not found -> create a new entry
            if (!found) {
                Entry<K, V> newEntry = new Entry<K, V>(key, value, hash, table[index]);
                table[index] = newEntry;
                Queue.Node<LruEntry> lruElem = lru.insert(new LruEntry(index, newEntry));
                newEntry.queueEntry = lruElem;
                
            }
        }
        
        // evict a value to free space if we exceed the size
        if (lru.getSize() > size) {
            LruEntry toClear = lru.extract(); // extract the least recently used
            clear(toClear.bucket, toClear.entry);
        }
    }