Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

182
LINES

< > BotCompany Repo | #1011872 // ExpiringHashMap - use ExpiringMap2 instead

JavaX fragment (include)

1  
// Copyright (c) 2017 Pierantonio Cangianiello (original name: SelfExpiringHashMap)
2  
 
3  
// thread-safe.
4  
sclass ExpiringHashMap<K, V> implements Map<K, V> {
5  
    final Map<K, V> internalMap;
6  
    final Map<K, ExpiringKey<K>> expiringKeys;
7  
    final DelayQueue<ExpiringKey> delayQueue = new DelayQueue<ExpiringKey>();
8  
9  
    long maxLifeTimeMillis;
10  
    bool renewOnGet, renewOnOverwrite = true;
11  
12  
    *() {
13  
      this(Long.MAX_VALUE);
14  
    }
15  
16  
    *(long defaultMaxLifeTimeMillis) {
17  
      internalMap = new ConcurrentHashMap<K, V>();
18  
      expiringKeys = new WeakHashMap<K, ExpiringKey<K>>();
19  
      this.maxLifeTimeMillis = defaultMaxLifeTimeMillis;
20  
    }
21  
22  
    public int size() {
23  
        cleanup();
24  
        return internalMap.size();
25  
    }
26  
    
27  
    public boolean isEmpty() {
28  
        cleanup();
29  
        return internalMap.isEmpty();
30  
    }
31  
32  
    public boolean containsKey(Object key) {
33  
        cleanup();
34  
        return internalMap.containsKey((K) key);
35  
    }
36  
37  
    public boolean containsValue(Object value) {
38  
        cleanup();
39  
        return internalMap.containsValue((V) value);
40  
    }
41  
42  
    public V get(Object key) {
43  
        cleanup();
44  
        if (renewOnGet) renewKey((K) key);
45  
        return internalMap.get((K) key);
46  
    }
47  
48  
    public V put(K key, V value) {
49  
        return this.put(key, value, maxLifeTimeMillis);
50  
    }
51  
52  
    public V put(K key, V value, long lifeTimeMillis) {
53  
        cleanup();
54  
        ExpiringKey delayedKey = new ExpiringKey(key, lifeTimeMillis);
55  
        ExpiringKey oldKey = expiringKeys.put((K) key, delayedKey);
56  
        if(oldKey != null) {
57  
            if (!renewOnOverwrite) {
58  
              delayedKey.startTime = oldKey.startTime;
59  
              delayedKey.maxLifeTimeMillis = oldKey.maxLifeTimeMillis;
60  
            }
61  
            expireKey(oldKey);
62  
            expiringKeys.put((K) key, delayedKey);
63  
        }
64  
        delayQueue.offer(delayedKey);
65  
        return internalMap.put(key, value);
66  
    }
67  
68  
    public V remove(Object key) {
69  
        V removedValue = internalMap.remove((K) key);
70  
        expireKey(expiringKeys.remove((K) key));
71  
        return removedValue;
72  
    }
73  
74  
    public void putAll(Map<? extends K, ? extends V> m) {
75  
        throw new UnsupportedOperationException();
76  
    }
77  
78  
    public boolean renewKey(K key) {
79  
        ExpiringKey<K> delayedKey = expiringKeys.get((K) key);
80  
        if (delayedKey != null) {
81  
            delayedKey.renew();
82  
            return true;
83  
        }
84  
        return false;
85  
    }
86  
87  
    private void expireKey(ExpiringKey<K> delayedKey) {
88  
        if (delayedKey != null) {
89  
            delayedKey.expire();
90  
            cleanup();
91  
        }
92  
    }
93  
94  
    public void clear() {
95  
        delayQueue.clear();
96  
        expiringKeys.clear();
97  
        internalMap.clear();
98  
    }
99  
100  
    public Set<K> keySet() {
101  
      cleanup();
102  
      ret internalMap.keySet(); // TODO: sync
103  
    }
104  
105  
    public Collection<V> values() {
106  
        throw new UnsupportedOperationException();
107  
    }
108  
109  
    public Set<Entry<K, V>> entrySet() {
110  
        throw new UnsupportedOperationException();
111  
    }
112  
113  
    private void cleanup() {
114  
        ExpiringKey<K> delayedKey = delayQueue.poll();
115  
        while (delayedKey != null) {
116  
            internalMap.remove(delayedKey.getKey());
117  
            expiringKeys.remove(delayedKey.getKey());
118  
            delayedKey = delayQueue.poll();
119  
        }
120  
    }
121  
122  
    class ExpiringKey<K> implements Delayed {
123  
124  
        private long startTime = System.currentTimeMillis();
125  
        private long maxLifeTimeMillis;
126  
        private final K key;
127  
128  
        public ExpiringKey(K key, long maxLifeTimeMillis) {
129  
            this.maxLifeTimeMillis = maxLifeTimeMillis;
130  
            this.key = key;
131  
        }
132  
133  
        public K getKey() {
134  
            return key;
135  
        }
136  
137  
        public boolean equals(Object obj) {
138  
            if (obj == null) {
139  
                return false;
140  
            }
141  
            if (getClass() != obj.getClass()) {
142  
                return false;
143  
            }
144  
            final ExpiringKey<K> other = (ExpiringKey<K>) obj;
145  
            if (this.key != other.key && (this.key == null || !this.key.equals(other.key))) {
146  
                return false;
147  
            }
148  
            return true;
149  
        }
150  
151  
        public int hashCode() {
152  
            int hash = 7;
153  
            hash = 31 * hash + (this.key != null ? this.key.hashCode() : 0);
154  
            return hash;
155  
        }
156  
157  
        public long getDelay(TimeUnit unit) {
158  
            return unit.convert(getDelayMillis(), TimeUnit.MILLISECONDS);
159  
        }
160  
161  
        private long getDelayMillis() {
162  
            return (startTime + maxLifeTimeMillis) - System.currentTimeMillis();
163  
        }
164  
165  
        public void renew() {
166  
            startTime = System.currentTimeMillis();
167  
        }
168  
169  
        public void expire() {
170  
            startTime =  System.currentTimeMillis() - maxLifeTimeMillis - 1;
171  
        }
172  
173  
        public int compareTo(Delayed that) {
174  
            return Long.compare(this.getDelayMillis(), ((ExpiringKey) that).getDelayMillis());
175  
        }
176  
    }
177  
    
178  
    ExpiringHashMap<K, V> dontRenewOnOverwrite() {
179  
      renewOnOverwrite = false;
180  
      this;
181  
    }
182  
}

download  show line numbers  debug dex  old transpilations   

Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

Comments [hide]

ID Author/Program Comment Date
1359 stefan From https://gist.github.com/pcan/16faf4e59942678377e0 2017-11-09 01:19:11

add comment

Snippet ID: #1011872
Snippet name: ExpiringHashMap - use ExpiringMap2 instead
Eternal ID of this version: #1011872/12
Text MD5: b474ca9479d962e486b49f813d521719
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2018-07-14 12:14:12
Source code size: 5235 bytes / 182 lines
Pitched / IR pitched: No / No
Views / Downloads: 639 / 1264
Version history: 11 change(s)
Referenced in: [show references]