View Javadoc

1   package com.atlassian.vcache;
2   
3   import com.atlassian.annotations.PublicApi;
4   
5   import java.util.Arrays;
6   import java.util.Map;
7   import java.util.Optional;
8   import java.util.Set;
9   import java.util.function.Function;
10  import java.util.function.Supplier;
11  
12  /**
13   * Represents the common operations that can be performed on a JVM local cache.
14   *
15   * @param <K> the key type
16   * @param <V> the value type
17   * @since 1.0
18   */
19  @PublicApi
20  public interface LocalCacheOperations<K, V> {
21      /**
22       * Returns a value that is associated with a specified key.
23       *
24       * @param key the key to check.
25       * @return an {@link Optional} which may contain the value associated with the key.
26       */
27      Optional<V> get(K key);
28  
29      /**
30       * Returns a value that may be associated with a specified key.
31       * <p>Notes:</p>
32       * <ul>
33       * <li>
34       * If no entry for the specified key exists, then the specified <tt>supplier</tt> is called to create
35       * an entry in the cache, before it is returned.
36       * </li>
37       * <li>
38       * The <tt>supplier</tt> implementation needs to be multi-thread safe as it may be called concurrently
39       * if multiple threads call this method.
40       * </li>
41       * </ul>
42       *
43       * @param key      the key uniquely identifying the value to be retrieved
44       * @param supplier used to generate the value, if one does not exist already for the key. The supplier may not
45       *                 return {@code null}.
46       * @return the value associated with the key.
47       */
48      V get(K key, Supplier<? extends V> supplier);
49  
50      /**
51       * Returns the values that are associated with the specified keys. It is equivalent to calling
52       * {@link #getBulk(Function, Iterable)} passing {@code factory} and {@code Arrays.asList(keys)} as the parameters.
53       *
54       * @param factory used to generate the values for the keys that do not have entries. The factory must return a
55       *                map containing only a non-null value for each supplied key. Extra keys are not allowed.
56       * @param keys    the keys to retrieve
57       * @return A {@link Map} that is keyed on the {@code keys} specified. Each entry in the {@link Map} will have
58       * the value associated with the key.
59       * @see #getBulk(Function, Iterable)
60       */
61      @SuppressWarnings("unchecked")
62      default Map<K, V> getBulk(Function<Set<K>, Map<K, V>> factory, K... keys) {
63          return getBulk(factory, Arrays.asList(keys));
64      }
65  
66      /**
67       * Returns the values that are associated with the specified keys.
68       * <p>Notes:</p>
69       * <ul>
70       * <li>
71       * <b>WARNING:</b> this method is not multi-thread safe in conjunction with any methods that make single key
72       * mutations, such as {@link #remove(Object)} or {@link #removeIf(Object, Object)}. Caller beware.
73       * </li>
74       * <li>
75       * If there are any keys for which no entry exists, then the given <tt>factory</tt> is called exactly once with
76       * the argument being a <tt>Set</tt> containing exactly the keys for which no entry existed.
77       * The return value of the <tt>factory</tt> is used to populate the missing entries in the cache,
78       * and then the map of all requested keys to values is returned.
79       * </li>
80       * <li>
81       * The call to the factory is made on the thread which calls <tt>getBulk</tt>.
82       * </li>
83       * <li>
84       * Despite the fact that the keys are an <tt>Iterable</tt>, no guarantees are made about the order in which
85       * the cache is populated, nor the order in which the <tt>Set</tt> passed to the factory is iterated,
86       * nor in which the returned <tt>Map</tt> is iterated.
87       * </li>
88       * </ul>
89       *
90       * @param factory used to generate the values for the keys that do not have entries. The factory must return a
91       *                map containing only a non-null value for each supplied key. Extra keys are not allowed.
92       * @param keys    the keys to retrieve
93       * @return A {@link Map} that is keyed on the {@code keys} specified. Each entry in the {@link Map} will have
94       * the value associated with the key.
95       */
96      Map<K, V> getBulk(Function<Set<K>, Map<K, V>> factory, Iterable<K> keys);
97  
98      /**
99       * Unconditionally puts the value under the specified key.
100      *
101      * @param key   the key to put the data under
102      * @param value the value to associate with the key.
103      */
104     void put(K key, V value);
105 
106     /**
107      * Conditionally puts the value under the specified key, if no entry currently exists. Returns the current
108      * value associated with the key, if one currently exists.
109      *
110      * @param key   the key to put the data under
111      * @param value the value to associate with the key.
112      * @return {@link Optional#EMPTY} is no entry previously existed, otherwise the {@link Optional} contains
113      * the current value.
114      */
115     Optional<V> putIfAbsent(K key, V value);
116 
117     /**
118      * Conditionally replaces the value associated with a key, iff:
119      * <ul>
120      * <li>An entry already exists for the key</li>
121      * <li>The current value matches the supplied <tt>currentValue</tt> using {@link Object#equals(Object)}</li>
122      * </ul>
123      *
124      * @param key          the key to replace data under
125      * @param currentValue the current value to match
126      * @param newValue     the replacement value
127      * @return whether the current value are replaced with the supplied <tt>newValue</tt>
128      */
129     boolean replaceIf(K key, V currentValue, V newValue);
130 
131     /**
132      * Conditionally removed an entry for a specified key, iff:
133      * <ul>
134      * <li>An entry already exists for the key</li>
135      * <li>The current value matches the supplied <tt>value</tt> using {@link Object#equals(Object)}</li>
136      * </ul>
137      *
138      * @param key   the key of the entry to remove conditionally
139      * @param value the current value to match
140      * @return whether an entry was removed
141      */
142     boolean removeIf(K key, V value);
143 
144     /**
145      * Removes the entries for the supplied key.
146      *
147      * @param key the key of the entry to remove
148      */
149     void remove(K key);
150 
151     /**
152      * Removes all the entries in the cache.
153      */
154     void removeAll();
155 }