All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cc.neckbeard.utils.ExpiringSet Maven / Gradle / Ivy

The newest version!
package cc.neckbeard.utils;

import org.jetbrains.annotations.NotNull;

import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Automatically clears expired entries on access.
 * 

* Backed by a ConcurrentHashMap. *

* Only timings equal or greater then 5 milliseconds are supported! * * @param Type of entries. */ public class ExpiringSet implements Set { private final Map map = new ConcurrentHashMap<>(); private final int ttl; private final ChronoUnit unit; /** * Only timings equal or greater then 5 milliseconds are supported! * * @param ttl Time value until expiration * @param unit Time unit */ public ExpiringSet(int ttl, ChronoUnit unit) { if ((unit == ChronoUnit.NANOS && ttl < 5_000_000) || (unit == ChronoUnit.MICROS && ttl < 5_000) || (unit == ChronoUnit.MILLIS && ttl < 5)) throw new IllegalArgumentException("ExpiringBoolean timings smaller then 5 milliseconds are not supported due to inconsistency!"); this.ttl = ttl; this.unit = unit; } private void removeExpired() { for (Map.Entry entry : map.entrySet()) { if (!entry.getValue().isValid()) { map.remove(entry.getKey()); } } } @Override public boolean add(final @NotNull T element) { add(element, new ExpiringFlag(ttl, unit)); // set always changes because of new timeout return true; } public boolean add(final @NotNull T element, final @NotNull ExpiringFlag flag) { map.put(element, flag); // set always changes because of new timeout return true; } @Override public boolean addAll(final @NotNull Collection collection) { addAll(collection, new ExpiringFlag(ttl, unit)); // set always changes because of new timeout return true; } public boolean addAll(final @NotNull Collection collection, final @NotNull ExpiringFlag flag) { for (T element : collection) add(element, flag); // set always changes because of new timeout return true; } @Override public void clear() { map.clear(); } @Override public int size() { removeExpired(); return map.keySet().size(); } @Override public boolean isEmpty() { removeExpired(); return map.isEmpty(); } @Override public boolean contains(final @NotNull Object element) { removeExpired(); //noinspection SuspiciousMethodCalls return map.containsKey(element); } @Override public boolean containsAll(final @NotNull Collection collection) { removeExpired(); for (Object element : collection) if (!contains(element)) return false; return true; } @Override public boolean remove(final @NotNull Object element) { removeExpired(); int size = map.size(); map.remove(element); return size != map.size(); } @Override public boolean removeAll(final @NotNull Collection collection) { removeExpired(); boolean changed = false; for (Object element : collection) if (remove(element)) changed = true; return changed; } @Override public boolean retainAll(final @NotNull Collection collection) { removeExpired(); int size = map.size(); for (T element : map.keySet()) if (!collection.contains(element)) map.remove(element); return size != map.size(); } @NotNull @Override public Iterator iterator() { removeExpired(); return map.keySet().iterator(); } @NotNull @Override public Object @NotNull [] toArray() { removeExpired(); return map.keySet().toArray(); } @NotNull @Override public U @NotNull [] toArray(final @NotNull U @NotNull [] array) { removeExpired(); //noinspection SuspiciousToArrayCall return map.keySet().toArray(array); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy