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)

// 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

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: 733 / 1362
Version history: 11 change(s)
Referenced in: #1034167 - Standard Classes + Interfaces (LIVE, continuation of #1003674)