// Copyright (c) 2017 Pierantonio Cangianiello (original name: SelfExpiringHashMap) // thread-safe. sclass ExpiringHashMap<K, V> implements Map<K, V> { final Map<K, V> internalMap; final Map<K, ExpiringKey<K>> expiringKeys; final DelayQueue<ExpiringKey> delayQueue = new DelayQueue<ExpiringKey>(); long maxLifeTimeMillis; bool renewOnGet, renewOnOverwrite = true; *() { this(Long.MAX_VALUE); } *(long defaultMaxLifeTimeMillis) { internalMap = new ConcurrentHashMap<K, V>(); expiringKeys = new WeakHashMap<K, ExpiringKey<K>>(); this.maxLifeTimeMillis = defaultMaxLifeTimeMillis; } public int size() { cleanup(); return internalMap.size(); } public boolean isEmpty() { cleanup(); return internalMap.isEmpty(); } public boolean containsKey(Object key) { cleanup(); return internalMap.containsKey((K) key); } public boolean containsValue(Object value) { cleanup(); return internalMap.containsValue((V) value); } public V get(Object key) { cleanup(); if (renewOnGet) renewKey((K) key); return internalMap.get((K) key); } public V put(K key, V value) { return this.put(key, value, maxLifeTimeMillis); } public V put(K key, V value, long lifeTimeMillis) { cleanup(); ExpiringKey delayedKey = new ExpiringKey(key, lifeTimeMillis); ExpiringKey oldKey = expiringKeys.put((K) key, delayedKey); if(oldKey != null) { if (!renewOnOverwrite) { delayedKey.startTime = oldKey.startTime; delayedKey.maxLifeTimeMillis = oldKey.maxLifeTimeMillis; } expireKey(oldKey); expiringKeys.put((K) key, delayedKey); } delayQueue.offer(delayedKey); return internalMap.put(key, value); } public V remove(Object key) { V removedValue = internalMap.remove((K) key); expireKey(expiringKeys.remove((K) key)); return removedValue; } public void putAll(Map<? extends K, ? extends V> m) { throw new UnsupportedOperationException(); } public boolean renewKey(K key) { ExpiringKey<K> delayedKey = expiringKeys.get((K) key); if (delayedKey != null) { delayedKey.renew(); return true; } return false; } private void expireKey(ExpiringKey<K> delayedKey) { if (delayedKey != null) { delayedKey.expire(); cleanup(); } } public void clear() { delayQueue.clear(); expiringKeys.clear(); internalMap.clear(); } public Set<K> keySet() { cleanup(); ret internalMap.keySet(); // TODO: sync } public Collection<V> values() { throw new UnsupportedOperationException(); } public Set<Entry<K, V>> entrySet() { throw new UnsupportedOperationException(); } private void cleanup() { ExpiringKey<K> delayedKey = delayQueue.poll(); while (delayedKey != null) { internalMap.remove(delayedKey.getKey()); expiringKeys.remove(delayedKey.getKey()); delayedKey = delayQueue.poll(); } } class ExpiringKey<K> implements Delayed { private long startTime = System.currentTimeMillis(); private long maxLifeTimeMillis; private final K key; public ExpiringKey(K key, long maxLifeTimeMillis) { this.maxLifeTimeMillis = maxLifeTimeMillis; this.key = key; } public K getKey() { return key; } public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final ExpiringKey<K> other = (ExpiringKey<K>) obj; if (this.key != other.key && (this.key == null || !this.key.equals(other.key))) { return false; } return true; } public int hashCode() { int hash = 7; hash = 31 * hash + (this.key != null ? this.key.hashCode() : 0); return hash; } public long getDelay(TimeUnit unit) { return unit.convert(getDelayMillis(), TimeUnit.MILLISECONDS); } private long getDelayMillis() { return (startTime + maxLifeTimeMillis) - System.currentTimeMillis(); } public void renew() { startTime = System.currentTimeMillis(); } public void expire() { startTime = System.currentTimeMillis() - maxLifeTimeMillis - 1; } public int compareTo(Delayed that) { return Long.compare(this.getDelayMillis(), ((ExpiringKey) that).getDelayMillis()); } } ExpiringHashMap<K, V> dontRenewOnOverwrite() { renewOnOverwrite = false; this; } }
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
ID | Author/Program | Comment | Date |
---|---|---|---|
1359 | stefan | From https://gist.github.com/pcan/16faf4e59942678377e0 | 2017-11-09 01:19:11 |
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: | 732 / 1361 |
Version history: | 11 change(s) |
Referenced in: | [show references] |