У меня есть класс кеша памяти, который я использую для хранения объектов Product
и количества проданных предметов.
public class MemoryCache<K, V> {
private long timeToLive;
private LRUMap lruMap;
/**
* custom class that stores the cache value
* and the timestamp for the last access
*/
protected class CacheObject {
public long lastAccessed = System.currentTimeMillis();
public V value;
protected CacheObject(V value) {
this.value = value;
}
}
/**
* @param timeToLive this is the permitted period of time for an object to live since
* they are last accessed.
*
* <p>
* @param timerInterval For the expiration of items use the timestamp of the last access
* and in a separate thread remove the items when the time to live
* limit is reached. This is nice for reducing memory pressure for
* applications that have long idle time in between accessing the
* cached objects. We have disabled the cleanup for this case scenario
*
* <p>
* @param maxItems Cache will keep most recently used items if we will try to add more
* items then max specified. The Apache common collections have an LRUMap,
* which, removes the least used entries from a fixed size map
*/
public MemoryCache(long timeToLive, final long timerInterval, int maxItems) {
this.timeToLive = timeToLive * 1000;
lruMap = new LRUMap(maxItems);
if (this.timeToLive > 0 && timerInterval > 0) {
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(timerInterval * 1000);
} catch (InterruptedException ex) {
}
/*
* clean the objects from the cache that has reached
* the timeToLive period after the last access.
* */
cleanup();
}
}
});
t.setDaemon(true);
t.start();
}
}
/**
* insert a new key and value inside the cache memory
*
* @param key
* @param value
*/
public void put(K key, V value) {
synchronized (lruMap) {
if (key == null) {
return;
}
/**
* we have reached the max. size of items decided for the cache
* and hence, we are not allowed to add more items for now. We
* will need for the cache cleaning to add further items.
*/
if (lruMap.isFull()) {
return;
}
lruMap.put(key, new CacheObject(value));
}
}
/**
* retrieve the cache object from the memory using the key
*
* @param key
* @return
*/
@SuppressWarnings("unchecked")
public V get(K key) {
synchronized (lruMap) {
MapIterator iterator = lruMap.mapIterator();
K k = null;
V v = null;
CacheObject o = null;
while (iterator.hasNext()) {
k = (K) iterator.next();
v = (V) iterator.getValue();
Product product = (Product) k;
Product product1 = (Product) key;
if (product.getProductId().equalsIgnoreCase(product1.getProductId())) {
o = (CacheObject) v;
}
}
if (o == null) {
return null;
} else {
o.lastAccessed = System.currentTimeMillis();
return o.value;
}
}
}
/**
* remove a cache object from the memory using the key
*
* @param key
*/
public void remove(K key) {
synchronized (lruMap) {
lruMap.remove(key);
}
}
/**
* find the size of the memory cache
*
* @return size of the cache
*/
public int size() {
synchronized (lruMap) {
return lruMap.size();
}
}
/**
* we will look after the cache objects with a certain time interval
* that has stayed in the memory inactively more than the time to live
* period and remove them iteratively.
*/
@SuppressWarnings("unchecked")
public void cleanup() {
long now = System.currentTimeMillis();
ArrayList<K> deleteKey = null;
synchronized (lruMap) {
MapIterator iterator = lruMap.mapIterator();
deleteKey = new ArrayList<K>((lruMap.size() / 2) + 1);
K key = null;
CacheObject object = null;
while (iterator.hasNext()) {
key = (K) iterator.next();
object = (CacheObject) iterator.getValue();
if (object != null && (now > (object.lastAccessed + timeToLive))) {
deleteKey.add(key);
}
}
}
for (K key : deleteKey) {
synchronized (lruMap) {
lruMap.remove(key);
}
Thread.yield();
}
}
/**
* convert the cache full of items to regular HashMap with the same
* key and value pair
*
* @return
*/
public Map<Product, Integer> convertToMap() {
synchronized (lruMap) {
Map<Product, Integer> map = new HashMap<>();
MapIterator iterator = lruMap.mapIterator();
K k = null;
V v = null;
CacheObject o = null;
while (iterator.hasNext()) {
k = (K) iterator.next();
v = (V) iterator.getValue();
Product product = (Product) k;
// this fails right here
int value = Integer.parseInt(String.valueOf(v));
map.put(product, value);
}
return map;
}
}
}
Внутри класса API он представлен как
MemoryCache<Product, Integer> cache = new MemoryCache<>(1800, 500, 10000);
. Я храню данные о товарах, которые продаются в классе API,
cache.put(product, 0);
Класс продукта, определенный ниже,
@Entity
public class Product {
@Id
@Column(name = "productId")
private String productId;
@Column(name = "stockId")
private String id;
@Column(name = "stock_timestamp")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "UTC")
private Timestamp timestamp;
@Column(name = "quantity")
private int quantity;
public Product() {
}
public Product(String productId, Timestamp requestTimestamp, String id, Timestamp timestamp, int quantity) {
this.productId = productId;
this.id = id;
this.timestamp = timestamp;
this.quantity = quantity;
}
// getter, setter
// equals and hasCode
// toString
}
Метод convertToMap
в классе MemoryCache
берет хранилища кэшей и превращает их в HashMap
.В методе есть ошибка в строке, где я пытаюсь сохранить int
в качестве значения.
int value = Integer.parseInt(String.valueOf(v));
У меня есть скриншот для сеанса отладки.
Как видите, мне нужно получить значения (то есть 1000, 100) и указать их как value
предполагаемого HashMap
.Как правильно написать метод convertToMap
для этой цели?