Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 41 additions & 80 deletions json-path/src/main/java/com/jayway/jsonpath/spi/cache/LRUCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,101 +12,62 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.jayway.jsonpath.spi.cache;

import com.jayway.jsonpath.JsonPath;

import java.util.Deque;
import java.util.LinkedList;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

public class LRUCache implements Cache {

private final ReentrantLock lock = new ReentrantLock();

private final Map<String, JsonPath> map = new ConcurrentHashMap<String, JsonPath>();
private final Deque<String> queue = new LinkedList<String>();
private final int limit;

public LRUCache(int limit) {
this.limit = limit;
}

public void put(String key, JsonPath value) {
JsonPath oldValue = map.put(key, value);
if (oldValue != null) {
removeThenAddKey(key);
} else {
addKey(key);
}
if (map.size() > limit) {
map.remove(removeLast());
}
}

public JsonPath get(String key) {
JsonPath jsonPath = map.get(key);
if(jsonPath != null){
removeThenAddKey(key);
}
return jsonPath;
}

private void addKey(String key) {
lock.lock();
try {
queue.addFirst(key);
} finally {
lock.unlock();
}
}

private String removeLast() {
lock.lock();
try {
final String removedKey = queue.removeLast();
return removedKey;
} finally {
lock.unlock();
}
}

private void removeThenAddKey(String key) {
lock.lock();
try {
queue.removeFirstOccurrence(key);
queue.addFirst(key);
} finally {
lock.unlock();
}

}

private void removeFirstOccurrence(String key) {
lock.lock();
try {
queue.removeFirstOccurrence(key);
} finally {
lock.unlock();
}
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
private final int size;
private LinkedHashMap<String, JsonPath> hashMap;

public LRUCache(int size) {
this.size = size;
int capacity = (int) Math.ceil(size / DEFAULT_LOAD_FACTOR) + 1;
hashMap = new LinkedHashMap<String, JsonPath>(capacity, DEFAULT_LOAD_FACTOR, true) {
// (an anonymous inner class)
private static final long serialVersionUID = 1;

@Override
protected boolean removeEldestEntry(Map.Entry<String, JsonPath> eldest) {
return size() > LRUCache.this.size;
}
};
}

public void put(String key, JsonPath value) {
synchronized (this) {
hashMap.put(key, value);
}
}

public JsonPath getSilent(String key) {
return map.get(key);
public JsonPath get(String key) {
synchronized (this) {
return hashMap.get(key);
}
}

public void remove(String key) {
removeFirstOccurrence(key);
map.remove(key);
public JsonPath getSilent(String key) {
synchronized (this) {
return hashMap.get(key);
}
}

public int size() {
return map.size();
public int size() {
synchronized (this) {
return hashMap.size();
}
}

public String toString() {
return map.toString();
public String toString() {
synchronized (this) {
return hashMap.toString();
}
}
}
}