Bael 4464 (#11041)
* BAEL-4464 : how to implement LRU-Cache in java codes added * BAEL-4464 : how to implement LRU-Cache in java codes added - package named fixed * BAEL-4464 : how to implement LRU-Cache in java codes added - package named changed * BAEL-4464 : how to implement LRU-Cache in java codes added - unitTest fixed * BAEL-4464 : issues 4,5 fixed. * fixed some issues in BAEL-4464
This commit is contained in:
parent
b9571f02f5
commit
66b40ed662
|
@ -10,67 +10,62 @@ public class DoublyLinkedList<T> {
|
||||||
private LinkedListNode<T> head;
|
private LinkedListNode<T> head;
|
||||||
private LinkedListNode<T> tail;
|
private LinkedListNode<T> tail;
|
||||||
private AtomicInteger size;
|
private AtomicInteger size;
|
||||||
private ReentrantReadWriteLock.ReadLock readLock;
|
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
private ReentrantReadWriteLock.WriteLock writeLock;
|
|
||||||
|
|
||||||
|
|
||||||
public DoublyLinkedList() {
|
public DoublyLinkedList() {
|
||||||
this.dummyNode = new DummyNode<T>(this);
|
this.dummyNode = new DummyNode<T>(this);
|
||||||
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
|
||||||
readLock = lock.readLock();
|
|
||||||
writeLock = lock.writeLock();
|
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
writeLock.lock();
|
this.lock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
head = dummyNode;
|
head = dummyNode;
|
||||||
tail = dummyNode;
|
tail = dummyNode;
|
||||||
size = new AtomicInteger(0);
|
size = new AtomicInteger(0);
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
this.lock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
readLock.lock();
|
this.lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
return size.get();
|
return size.get();
|
||||||
} finally {
|
} finally {
|
||||||
readLock.unlock();
|
this.lock.readLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
readLock.lock();
|
this.lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
return head.isEmpty();
|
return head.isEmpty();
|
||||||
} finally {
|
} finally {
|
||||||
readLock.unlock();
|
this.lock.readLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(T value) {
|
public boolean contains(T value) {
|
||||||
readLock.lock();
|
this.lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
return search(value).hasElement();
|
return search(value).hasElement();
|
||||||
} finally {
|
} finally {
|
||||||
readLock.unlock();
|
this.lock.readLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinkedListNode<T> search(T value) {
|
public LinkedListNode<T> search(T value) {
|
||||||
readLock.lock();
|
this.lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
return head.search(value);
|
return head.search(value);
|
||||||
} finally {
|
} finally {
|
||||||
readLock.unlock();
|
this.lock.readLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinkedListNode<T> add(T value) {
|
public LinkedListNode<T> add(T value) {
|
||||||
writeLock.lock();
|
this.lock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
head = new Node<T>(value, head, this);
|
head = new Node<T>(value, head, this);
|
||||||
if (tail.isEmpty()) {
|
if (tail.isEmpty()) {
|
||||||
|
@ -79,12 +74,12 @@ public class DoublyLinkedList<T> {
|
||||||
size.incrementAndGet();
|
size.incrementAndGet();
|
||||||
return head;
|
return head;
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
this.lock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addAll(Collection<T> values) {
|
public boolean addAll(Collection<T> values) {
|
||||||
writeLock.lock();
|
this.lock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
for (T value : values) {
|
for (T value : values) {
|
||||||
if (add(value).isEmpty()) {
|
if (add(value).isEmpty()) {
|
||||||
|
@ -93,12 +88,12 @@ public class DoublyLinkedList<T> {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
this.lock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinkedListNode<T> remove(T value) {
|
public LinkedListNode<T> remove(T value) {
|
||||||
writeLock.lock();
|
this.lock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
LinkedListNode<T> linkedListNode = head.search(value);
|
LinkedListNode<T> linkedListNode = head.search(value);
|
||||||
if (!linkedListNode.isEmpty()) {
|
if (!linkedListNode.isEmpty()) {
|
||||||
|
@ -113,12 +108,12 @@ public class DoublyLinkedList<T> {
|
||||||
}
|
}
|
||||||
return linkedListNode;
|
return linkedListNode;
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
this.lock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinkedListNode<T> removeTail() {
|
public LinkedListNode<T> removeTail() {
|
||||||
writeLock.lock();
|
this.lock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
LinkedListNode<T> oldTail = tail;
|
LinkedListNode<T> oldTail = tail;
|
||||||
if (oldTail == head) {
|
if (oldTail == head) {
|
||||||
|
@ -132,7 +127,7 @@ public class DoublyLinkedList<T> {
|
||||||
}
|
}
|
||||||
return oldTail;
|
return oldTail;
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
this.lock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +136,7 @@ public class DoublyLinkedList<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinkedListNode<T> updateAndMoveToFront(LinkedListNode<T> node, T newValue) {
|
public LinkedListNode<T> updateAndMoveToFront(LinkedListNode<T> node, T newValue) {
|
||||||
writeLock.lock();
|
this.lock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
if (node.isEmpty() || (this != (node.getListReference()))) {
|
if (node.isEmpty() || (this != (node.getListReference()))) {
|
||||||
return dummyNode;
|
return dummyNode;
|
||||||
|
@ -150,7 +145,7 @@ public class DoublyLinkedList<T> {
|
||||||
add(newValue);
|
add(newValue);
|
||||||
return head;
|
return head;
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
this.lock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.baeldung.lrucache;
|
package com.baeldung.lrucache;
|
||||||
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
@ -10,21 +9,17 @@ public class LRUCache<K, V> implements Cache<K, V> {
|
||||||
private int size;
|
private int size;
|
||||||
private Map<K, LinkedListNode<CacheElement<K, V>>> linkedListNodeMap;
|
private Map<K, LinkedListNode<CacheElement<K, V>>> linkedListNodeMap;
|
||||||
private DoublyLinkedList<CacheElement<K, V>> doublyLinkedList;
|
private DoublyLinkedList<CacheElement<K, V>> doublyLinkedList;
|
||||||
private ReentrantReadWriteLock.ReadLock readLock;
|
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
private ReentrantReadWriteLock.WriteLock writeLock;
|
|
||||||
|
|
||||||
public LRUCache(int size) {
|
public LRUCache(int size) {
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.linkedListNodeMap = new Hashtable<>(size);
|
this.linkedListNodeMap = new ConcurrentHashMap<>(size);
|
||||||
this.doublyLinkedList = new DoublyLinkedList<>();
|
this.doublyLinkedList = new DoublyLinkedList<>();
|
||||||
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
|
||||||
this.readLock = lock.readLock();
|
|
||||||
this.writeLock = lock.writeLock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean put(K key, V value) {
|
public boolean put(K key, V value) {
|
||||||
writeLock.lock();
|
this.lock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
CacheElement<K, V> item = new CacheElement<K, V>(key, value);
|
CacheElement<K, V> item = new CacheElement<K, V>(key, value);
|
||||||
LinkedListNode<CacheElement<K, V>> newNode;
|
LinkedListNode<CacheElement<K, V>> newNode;
|
||||||
|
@ -43,13 +38,13 @@ public class LRUCache<K, V> implements Cache<K, V> {
|
||||||
this.linkedListNodeMap.put(key, newNode);
|
this.linkedListNodeMap.put(key, newNode);
|
||||||
return true;
|
return true;
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
this.lock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<V> get(K key) {
|
public Optional<V> get(K key) {
|
||||||
readLock.lock();
|
this.lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
LinkedListNode<CacheElement<K, V>> linkedListNode = this.linkedListNodeMap.get(key);
|
LinkedListNode<CacheElement<K, V>> linkedListNode = this.linkedListNodeMap.get(key);
|
||||||
if (linkedListNode != null && !linkedListNode.isEmpty()) {
|
if (linkedListNode != null && !linkedListNode.isEmpty()) {
|
||||||
|
@ -58,17 +53,17 @@ public class LRUCache<K, V> implements Cache<K, V> {
|
||||||
}
|
}
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
} finally {
|
} finally {
|
||||||
readLock.unlock();
|
this.lock.readLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
readLock.lock();
|
this.lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
return doublyLinkedList.size();
|
return doublyLinkedList.size();
|
||||||
} finally {
|
} finally {
|
||||||
readLock.unlock();
|
this.lock.readLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,18 +74,18 @@ public class LRUCache<K, V> implements Cache<K, V> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
writeLock.lock();
|
this.lock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
linkedListNodeMap.clear();
|
linkedListNodeMap.clear();
|
||||||
doublyLinkedList.clear();
|
doublyLinkedList.clear();
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
this.lock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean evictElement() {
|
private boolean evictElement() {
|
||||||
writeLock.lock();
|
this.lock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
LinkedListNode<CacheElement<K, V>> linkedListNode = doublyLinkedList.removeTail();
|
LinkedListNode<CacheElement<K, V>> linkedListNode = doublyLinkedList.removeTail();
|
||||||
if (linkedListNode.isEmpty()) {
|
if (linkedListNode.isEmpty()) {
|
||||||
|
@ -99,7 +94,7 @@ public class LRUCache<K, V> implements Cache<K, V> {
|
||||||
linkedListNodeMap.remove(linkedListNode.getElement().getKey());
|
linkedListNodeMap.remove(linkedListNode.getElement().getKey());
|
||||||
return true;
|
return true;
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
this.lock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue