cache

added entrySet, values and containsKey. throw KeyNotFoundException.

7/2/2019 3:29:32 AM

Details

diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/Cache.java b/src/main/java/br/ufrgs/inf/prosoft/cache/Cache.java
index 044ba54..f71673a 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/Cache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/Cache.java
@@ -5,6 +5,7 @@
  */
 package br.ufrgs.inf.prosoft.cache;
 
+import java.util.Optional;
 import java.util.function.Supplier;
 
 /**
@@ -19,31 +20,31 @@ public interface Cache<K, V> {
 
     public void put(K key, V value);
 
-    public V get(K key);
+    public V get(K key) throws KeyNotFoundException;
 
     public void invalidate(K key);
 
     public default V computeIfAbsent(K key, Supplier<V> supplier, long timeToLive) {
-        synchronized (key) {
-            V get = get(key);
-            if (get != null) {
+        synchronized (Optional.ofNullable(key)) {
+            try {
+                return get(key);
+            } catch (KeyNotFoundException ex) {
+                V get = supplier.get();
+                put(key, get, timeToLive);
                 return get;
             }
-            get = supplier.get();
-            put(key, get, timeToLive);
-            return get;
         }
     }
 
     public default V computeIfAbsent(K key, Supplier<V> supplier) {
-        synchronized (key) {
-            V get = get(key);
-            if (get != null) {
+        synchronized (Optional.ofNullable(key)) {
+            try {
+                return get(key);
+            } catch (KeyNotFoundException ex) {
+                V get = supplier.get();
+                put(key, get);
                 return get;
             }
-            get = supplier.get();
-            put(key, get);
-            return get;
         }
     }
 }
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/GetterCache.java b/src/main/java/br/ufrgs/inf/prosoft/cache/GetterCache.java
index d09a5de..7e5b720 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/GetterCache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/GetterCache.java
@@ -34,7 +34,7 @@ public class GetterCache<V> extends MultiCache<Void, V> {
         super.put(null, value);
     }
 
-    public V get() {
+    public V get() throws KeyNotFoundException {
         return super.get(null);
     }
 
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/KeyNotFoundException.java b/src/main/java/br/ufrgs/inf/prosoft/cache/KeyNotFoundException.java
new file mode 100644
index 0000000..ee90e64
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/KeyNotFoundException.java
@@ -0,0 +1,14 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package br.ufrgs.inf.prosoft.cache;
+
+/**
+ *
+ * @author romulo
+ */
+public class KeyNotFoundException extends Exception {
+
+}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/MultiCache.java b/src/main/java/br/ufrgs/inf/prosoft/cache/MultiCache.java
index 580d779..784df70 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/MultiCache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/MultiCache.java
@@ -6,9 +6,12 @@
 package br.ufrgs.inf.prosoft.cache;
 
 import java.util.HashMap;
-import java.util.Optional;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.util.stream.Collectors;
 
 /**
  *
@@ -19,7 +22,7 @@ import java.util.logging.Logger;
 public class MultiCache<K, V> implements Cache<K, V> {
 
     private static final boolean CACHE_REGISTER_SIZE = System.getenv("CACHE_REGISTER_SIZE") != null && System.getenv("CACHE_REGISTER_SIZE").equals("true");
-    private final HashMap<K, Optional<V>> map;
+    private final HashMap<K, V> map;
     private final HashMap<K, Thread> keyHasTTL;
     private final CachePerformance cachePerformance;
     private static final Logger LOGGER = Logger.getLogger(Cache.class.getName());
@@ -60,8 +63,7 @@ public class MultiCache<K, V> implements Cache<K, V> {
     @Override
     public void put(K key, V value) {
         invalidate(key);
-        Optional<V> optional = Optional.ofNullable(value);
-        this.map.put(key, optional);
+        this.map.put(key, value);
         String identifier = getIdentifier(value);
         if (CACHE_REGISTER_SIZE) {
             this.cachePerformance.registerEvent(EventType.ADDITION, identifier, CachePerformance.calculateObjectSize(value));
@@ -72,13 +74,12 @@ public class MultiCache<K, V> implements Cache<K, V> {
     }
 
     @Override
-    public V get(K key) {
-        Optional<V> optional = this.map.get(key);
-        if (optional == null) {
+    public V get(K key) throws KeyNotFoundException {
+        if (!this.map.containsKey(key)) {
             this.cachePerformance.registerEvent(EventType.MISS);
-            return null;
+            throw new KeyNotFoundException();
         }
-        V get = optional.orElse(null);
+        V get = this.map.get(key);
         String identifier = getIdentifier(get);
         if (CACHE_REGISTER_SIZE) {
             this.cachePerformance.registerEvent(EventType.HIT, identifier, CachePerformance.calculateObjectSize(get));
@@ -94,9 +95,8 @@ public class MultiCache<K, V> implements Cache<K, V> {
         if (timeToLiveThread != null) {
             timeToLiveThread.interrupt();
         }
-        Optional<V> optional = this.map.remove(key);
-        if (optional != null) {
-            V remove = optional.orElse(null);
+        if (this.map.containsKey(key)) {
+            V remove = this.map.remove(key);
             String identifier = getIdentifier(remove);
             if (CACHE_REGISTER_SIZE) {
                 this.cachePerformance.registerEvent(EventType.INVALIDATION, identifier, CachePerformance.calculateObjectSize(remove));
@@ -106,6 +106,21 @@ public class MultiCache<K, V> implements Cache<K, V> {
         }
     }
 
+    public Set<Map.Entry<K, V>> entrySet() {
+        return this.map.entrySet().stream()
+                .collect(Collectors.
+                        toMap(entry -> entry.getKey(), entry -> entry.getValue())
+                ).entrySet();
+    }
+
+    public List<V> values() {
+        return this.map.values().stream().collect(Collectors.toList());
+    }
+
+    public boolean containsKey(K key) {
+        return this.map.containsKey(key);
+    }
+
     private String getIdentifier(V value) {
         return value != null ? String.valueOf(value.hashCode()) : "null";
     }