sclass ExpiringMap2 extends AbstractMap { Map> byKey; new PriorityBlockingQueue> queue; long standardExpiryTime; // ms bool renewOnOverwrite = true; O onChange; *() {} *(long *standardExpiryTime) {} *(long *standardExpiryTime, O *onChange) {} void clean() { Pair p; while ((p = queue.peek()) != null && sysTime() >= p.a) { p = queue.poll(); Pair v = byKey.get(p.a); if (v != null && v.a == p.a) { byKey.remove(p.a); change(); } } } void change() { callF(onChange); } public B put(A a, B b) { clean(); timeout = sysTime()+standardExpiryTime; Pair p = byKey.get(a); if (p != null && renewOnOverwrite) queue.remove(PairComparedByA(p.a, a)); byKey.put(a, pair(timeout, b)); change(); if (renewOnOverwrite) queue.add(PairComparedByA(timeout, a)); ret pairB(p); } public B remove(O a) { clean(); Pair p = byKey.get(a); if (p == null) null; queue.remove(PairComparedByA(p.a, a)); byKey.remove(a); change(); ret p.b; } public B get(O a) { clean(); ret pairB(byKey.get(a)); } public Set> entrySet() { clean(); ret mapValues(f pairB, byKey).entrySet(); } public int size() { clean(); ret byKey.size(); } }