{"id":16921040,"url":"https://github.com/alxkm/cache","last_synced_at":"2025-04-11T11:31:01.996Z","repository":{"id":244590279,"uuid":"815686183","full_name":"alxkm/cache","owner":"alxkm","description":"Simple cache implementation on java","archived":false,"fork":false,"pushed_at":"2024-06-17T21:38:37.000Z","size":88,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-25T13:11:18.652Z","etag":null,"topics":["cache","cache-storage","java","lfu","lfu-algorithm","lfu-cache","lfu-implementation","lru","lru-cache","lru-eviction","lru-implementation","lrucache"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alxkm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-15T20:45:04.000Z","updated_at":"2025-02-22T18:18:30.000Z","dependencies_parsed_at":"2024-06-17T23:40:06.000Z","dependency_job_id":null,"html_url":"https://github.com/alxkm/cache","commit_stats":null,"previous_names":["alxkm/cache"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alxkm%2Fcache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alxkm%2Fcache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alxkm%2Fcache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alxkm%2Fcache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alxkm","download_url":"https://codeload.github.com/alxkm/cache/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248383893,"owners_count":21094627,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","cache-storage","java","lfu","lfu-algorithm","lfu-cache","lfu-implementation","lru","lru-cache","lru-eviction","lru-implementation","lrucache"],"created_at":"2024-10-13T19:50:27.251Z","updated_at":"2025-04-11T11:31:01.466Z","avatar_url":"https://github.com/alxkm.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Java CI with Gradle](https://github.com/alxkm/cache/actions/workflows/gradle.yml/badge.svg)](https://github.com/alxkm/cache/actions/workflows/gradle.yml)[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n# Cache Implementations\n\nThis repository contains implementations of both Least Recently Used (LRU) and Least Frequently Used (LFU) Cache in Java using various data structures:\n\n## LRU Cache Implementations\n\n1. **LRULinkedHashMapCache**: Implementation using `LinkedHashMap` to maintain insertion order.\n2. **LRUDoublyLinkedListCache**: Implementation using a custom doubly linked list and `HashMap`.\n3. **LRUHashMapQueueCache**: Implementation using `HashMap` and `Deque` (double-ended queue) for managing access order.\n\n### Overview\n\nLRU Cache is a caching technique where the least recently used items are removed from the cache when it exceeds its predefined capacity. This ensures that the cache doesn't grow indefinitely and optimizes access time by retaining frequently used items.\n\n### CacheService Interface\n\n#### Description\n`CacheService` defines the interface for the LRU Cache implementations.\n\n#### Methods\n- `put(K id, V value)`: Inserts a key-value pair into the cache. If the key already exists, updates the value and adjusts its position based on access.\n- `get(K id)`: Retrieves the value associated with the key from the cache. If the key exists, marks it as recently used.\n- `evict(K id)`: Removes the key-value pair from the cache.\n\n### Implementations\n\n#### 1. LRULinkedHashMapCache\n\n**Description**: LRU Cache implemented using `LinkedHashMap`, which maintains elements in the order of their access. When the capacity is exceeded, the least recently accessed entry is removed.\n\n**Constructor**\n```java\nLRULinkedHashMapCache(int capacity): Initializes the cache with a specified capacity.\n```\n\n**Time Complexity**\n- `put`: O(1)\n- `get`: O(1)\n- `evict`: O(1)\n\n#### 2. LRUDoublyLinkedListCache\n\n**Description**: LRU Cache implemented using a custom doubly linked list (`Node` class) and `HashMap`. This implementation manages the access order explicitly by moving nodes within the linked list.\n\n**Constructor**\n```java\nLRUDoublyLinkedListCache(int capacity): Initializes the cache with a specified capacity.\n```\n\n**Time Complexity**\n- `put`: O(1)\n- `get`: O(1)\n- `evict`: O(1)\n\n#### 3. LRUHashMapQueueCache\n\n**Description**: LRU Cache implemented using `HashMap` and `Deque` (specifically `LinkedList`), where `Deque` is used to maintain the order of keys based on their access time. The most recently accessed keys are moved to the front of the `Deque`.\n\n**Constructor**\n```java\nLRUHashMapQueueCache(int capacity): Initializes the cache with a specified capacity.\n```\n\n**Time Complexity**\n- `put`: O(1)\n- `get`: O(1)\n- `evict`: O(1)\n\n### Usage\n\nEach implementation provides the same interface (`CacheService`) for inserting, retrieving, and evicting elements from the cache. Here's an example of usage for all three classes:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        // Using LRULinkedHashMapCache\n        CacheService\u003cInteger, String\u003e linkedHashMapCache = new LRULinkedHashMapCache\u003c\u003e(3);\n        linkedHashMapCache.put(1, \"one\");\n        linkedHashMapCache.put(2, \"two\");\n        linkedHashMapCache.put(3, \"three\");\n        System.out.println(linkedHashMapCache.get(1)); // Output: one\n        linkedHashMapCache.put(4, \"four\");\n        System.out.println(linkedHashMapCache.get(2)); // Output: null (evicted)\n        linkedHashMapCache.put(5, \"five\");\n        System.out.println(linkedHashMapCache.get(3)); // Output: null (evicted)\n        System.out.println(linkedHashMapCache.get(4)); // Output: four\n        System.out.println(linkedHashMapCache.get(5)); // Output: five\n\n        // Using LRUDoublyLinkedListCache\n        CacheService\u003cInteger, String\u003e doublyLinkedListCache = new LRUDoublyLinkedListCache\u003c\u003e(3);\n        doublyLinkedListCache.put(1, \"one\");\n        doublyLinkedListCache.put(2, \"two\");\n        doublyLinkedListCache.put(3, \"three\");\n        System.out.println(doublyLinkedListCache.get(1)); // Output: one\n        doublyLinkedListCache.put(4, \"four\");\n        System.out.println(doublyLinkedListCache.get(2)); // Output: null (evicted)\n        doublyLinkedListCache.put(5, \"five\");\n        System.out.println(doublyLinkedListCache.get(3)); // Output: null (evicted)\n        System.out.println(doublyLinkedListCache.get(4)); // Output: four\n        System.out.println(doublyLinkedListCache.get(5)); // Output: five\n\n        // Using LRUHashMapQueueCache\n        CacheService\u003cInteger, String\u003e hashMapQueueCache = new LRUHashMapQueueCache\u003c\u003e(3);\n        hashMapQueueCache.put(1, \"one\");\n        hashMapQueueCache.put(2, \"two\");\n        hashMapQueueCache.put(3, \"three\");\n        System.out.println(hashMapQueueCache.get(1)); // Output: one\n        hashMapQueueCache.put(4, \"four\");\n        System.out.println(hashMapQueueCache.get(2)); // Output: null (evicted)\n        hashMapQueueCache.put(5, \"five\");\n        System.out.println(hashMapQueueCache.get(3)); // Output: null (evicted)\n        System.out.println(hashMapQueueCache.get(4)); // Output: four\n        System.out.println(hashMapQueueCache.get(5)); // Output: five\n    }\n}\n```\n\n\n## LFU Cache Implementations\n\n### Overview\n\nLFU Cache is a caching technique where the least frequently used items are removed from the cache when it exceeds its predefined capacity. This helps in retaining the most frequently accessed items in the cache.\n\n### LFUDoublyLinkedListCache Class\n\n#### Description\n`LFUDoublyLinkedListCache` is a Java implementation of an LFU Cache that uses a `HashMap` for quick access to cache entries and a custom doubly linked list to maintain frequency counts. This implementation ensures efficient retrieval, insertion, and eviction of cache entries based on their access frequency.\n\n#### Constructor\n```java\n/**\n * Constructs an LFU Cache with the specified capacity.\n *\n * @param capacity the capacity of the cache\n */\npublic LFUDoublyLinkedListCache(int capacity);\n```\n\n#### Methods\n```java\n/**\n * Adds an item to the cache. If the cache is full, evicts the least frequently used item.\n * If an item with the same key already exists, updates its value and frequency.\n *\n * @param id    the key with which the specified value is to be associated\n * @param value the value to be associated with the specified key\n */\n@Override\npublic void put(K id, V value);\n\n/**\n * Retrieves the value associated with the specified key. If the key is found,\n * increases its frequency.\n *\n * @param id the key whose associated value is to be returned\n * @return the value to which the specified key is mapped, or null if this cache contains no mapping for the key\n */\n@Override\npublic V get(K id);\n\n/**\n * Evicts the item with the specified key from the cache.\n *\n * @param id the key whose mapping is to be removed from the cache\n */\n@Override\npublic void evict(K id);\n```\n\n**Time Complexity**\n- `put`: O(1)\n- `get`: O(1)\n- `evict`: O(1)\n\n#### CacheNode Class\n\nRepresents a key-value pair with a frequency counter.\n\n```java\nprivate static class CacheNode\u003cK, V\u003e {\n    K key;\n    V value;\n    int frequency;\n\n    /**\n     * Constructs a new node with the specified key and value. Initializes the frequency to 1.\n     *\n     * @param key   the key of the node\n     * @param value the value of the node\n     */\n    CacheNode(K key, V value);\n}\n```\n\n### LFUTreeMapCache Class\n\n#### Description\n`LFUTreeMapCache` is a Java implementation of an LFU Cache that uses a `HashMap` for quick access to cache entries and a `TreeMap` to maintain frequency counts in sorted order. This implementation ensures efficient retrieval, insertion, and eviction of cache entries based on their access frequency.\n\n#### Constructor\n```java\n/**\n * Constructs an LFU Cache with the specified capacity.\n *\n * @param capacity the capacity of the cache\n */\npublic LFUTreeMapCache(int capacity);\n```\n\n#### Methods\n```java\n/**\n * Adds an item to the cache. If the cache is full, evicts the least frequently used item.\n * If an item with the same key already exists, updates its value and frequency.\n *\n * @param id    the key with which the specified value is to be associated\n * @param value the value to be associated with the specified key\n */\n@Override\npublic void put(K id, V value);\n\n/**\n * Retrieves the value associated with the specified key. If the key is found,\n * increases its frequency.\n *\n * @param id the key whose associated value is to be returned\n * @return the value to which the specified key is mapped, or null if this cache contains no mapping for the key\n */\n@Override\npublic V get(K id);\n\n/**\n * Evicts the item with the specified key from the cache.\n *\n * @param id the key whose mapping is to be removed from the cache\n */\n@Override\npublic void evict(K id);\n```\n\n**Time Complexity**\n- `put`: O(log n)\n- `get`: O(log n)\n- `evict`: O(log n)\n\n#### CacheNode Class\n\nRepresents a key-value pair with a frequency counter.\n\n```java\nprivate static class CacheNode\u003cK, V\u003e {\n    K key;\n    V value;\n    int frequency;\n\n    /**\n     * Constructs a new node with the specified key and value. Initializes the frequency to 1.\n     *\n     * @param key   the key of the node\n     * @param value the value of the node\n     */\n    CacheNode(K key, V value);\n}\n```\n\n### Example\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        LFUTreeMapCache\u003cInteger, String\u003e treeMapCache = new LFUTreeMapCache\u003c\u003e(3);\n        LFUDoublyLinkedListCache\u003cInteger, String\u003e linkedListCache = new LFUDoublyLinkedListCache\u003c\u003e(3);\n        \n        // Example usage for LFUTreeMapCache\n        treeMapCache.put(1, \"one\");\n        treeMapCache.put(2, \"two\");\n        treeMapCache.put(3, \"three\");\n        \n        System.out.println(treeMapCache.get(1)); // Outputs: one\n        \n        treeMapCache.put(4, \"four\"); // Evicts key 2, which is the least frequently used\n        \n        System.out.println(treeMapCache.get(2)); // Outputs: null (since key 2 has been evicted)\n        \n        treeMapCache.evict(3); // Manually evicts key 3\n        \n        System.out.println(treeMapCache.get(3)); // Outputs: null (since key 3 has been evicted)\n\n        // Example usage for LFUDoublyLinkedListCache\n        linkedListCache.put(1, \"one\");\n        linkedListCache.put(2, \"two\");\n        linkedListCache.put(3, \"three\");\n        \n        System.out.println(linkedListCache.get(1)); // Outputs: one\n        \n        linkedListCache.put(4, \"four\"); // Evicts key 2, which is the least frequently used\n        \n        System.out.println(linkedListCache.get(2)); // Outputs: null (since key 2 has been evicted)\n        \n        linkedListCache.evict(3); // Manually evicts key 3\n        \n        System.out.println(linkedListCache.get(3)); // Outputs: null (since key 3 has been evicted)\n    }\n}\n```\n\n## MRU Cache Implementation\n\n### Overview\n\nMRU (Most Recently Used) Cache is a caching technique where the most recently used items are removed from the cache when it exceeds its predefined capacity. This approach is useful in scenarios where the least recently used items are more likely to be needed again soon.\n\n### MRUCache Class\n\n#### Description\n`MRUCache` is a Java implementation of an MRU Cache that uses a `HashMap` for quick access to cache entries and a `LinkedList` to maintain the order of entries based on their access time. This implementation ensures efficient retrieval, insertion, and eviction of cache entries based on their most recent usage.\n\n#### Constructor\n```java\n/**\n * Constructs an MRU Cache with the specified capacity.\n *\n * @param capacity the capacity of the cache\n */\npublic MRUCache(int capacity);\n```\n\n#### Methods\n```java\n/**\n * Adds an item to the cache. If the cache is full, evicts the most recently used item.\n * If an item with the same key already exists, updates its value and marks it as recently used.\n *\n * @param id    the key with which the specified value is to be associated\n * @param value the value to be associated with the specified key\n */\n@Override\npublic void put(T id, V value);\n\n/**\n * Retrieves the value associated with the specified key. If the key is found,\n * marks it as recently used.\n *\n * @param id the key whose associated value is to be returned\n * @return the value to which the specified key is mapped, or null if this cache contains no mapping for the key\n */\n@Override\npublic V get(T id);\n\n/**\n * Evicts the item with the specified key from the cache.\n *\n * @param id the key whose mapping is to be removed from the cache\n */\n@Override\npublic void evict(T id);\n```\n\n**Time Complexity**\n- `put`: O(1)\n- `get`: O(1)\n- `evict`: O(1)\n\n### Example\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        CacheService\u003cInteger, String\u003e cache = new MRUCache\u003c\u003e(3);\n        \n        cache.put(1, \"one\");\n        cache.put(2, \"two\");\n        cache.put(3, \"three\");\n        \n        System.out.println(cache.get(1)); // Outputs: one\n        \n        cache.put(4, \"four\"); // Evicts key 1, which is the most recently used\n        \n        System.out.println(cache.get(1)); // Outputs: null (since key 1 has been evicted)\n        System.out.println(cache.get(2)); // Outputs: two\n        System.out.println(cache.get(3)); // Outputs: three\n        System.out.println(cache.get(4)); // Outputs: four\n        \n        cache.evict(2); // Manually evicts key 2\n        \n        System.out.println(cache.get(2)); // Outputs: null (since key 2 has been evicted)\n    }\n}\n```\n\n### Testing\n\nThe repository includes JUnit tests that validate the functionality of each cache implementation. These tests cover insertion, retrieval, eviction, and edge cases such as updating existing entries.\n\n### License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE.md) file for details.\n\nFeel free to fork and modify these implementations for your own use cases or contribute to enhance them further. If you have any questions or suggestions, please feel free to reach out or open an issue!\n\n## Contributing\n\nContributions are welcome! Please open an issue or submit a pull request for any improvements or bug fixes.\n\n## Acknowledgments\n\nThis implementation was inspired by various LFU and LRU cache algorithms and adapted for educational purposes. Special thanks to the open-source community for their contributions and ideas.\n\n## Contact\n\nFor any questions or suggestions, please feel free to reach out or open an issue!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falxkm%2Fcache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falxkm%2Fcache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falxkm%2Fcache/lists"}