package io.github.lucaseasedup.logit.common; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Queue; import java.util.Set; import java.util.TreeSet; public final class QueuedMap<K, V> implements Map<K, V> { @Override public synchronized V put(K key, V value) { if (key == null) throw new IllegalArgumentException(); if (keys.contains(key)) { return values.put(key, value); } else { enqueue(key, value); return null; } } @Override public synchronized V get(Object key) { if (key == null) throw new IllegalArgumentException(); return values.get(key); } @Override public synchronized V remove(Object key) { if (key == null) throw new IllegalArgumentException(); keys.remove(key); return values.remove(key); } public synchronized Map.Entry<K, V> remove() { final K key = keys.remove(); final V value = values.remove(key); return new Map.Entry<K, V>() { @Override public K getKey() { return key; } @Override public V getValue() { return value; } @Override public V setValue(V value) { throw new UnsupportedOperationException(); } }; } public synchronized Map.Entry<K, V> element() { final K key = keys.element(); final V value = values.get(key); return new Map.Entry<K, V>() { @Override public K getKey() { return key; } @Override public V getValue() { return value; } @Override public V setValue(V value) { throw new UnsupportedOperationException(); } }; } @Override public synchronized int size() { return keys.size(); } @Override public synchronized boolean isEmpty() { return size() == 0; } @Override public synchronized boolean containsKey(Object key) { return keys.contains(key); } @Override public synchronized boolean containsValue(Object value) { return values.containsValue(value); } @Override public Set<K> keySet() { Set<K> keySet = new TreeSet<>(); keySet.addAll(keys); return keySet; } @Override public Collection<V> values() { return values.values(); } @Override public Set<Map.Entry<K, V>> entrySet() { return values.entrySet(); } @Override public void putAll(Map<? extends K, ? extends V> m) { for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) { put(e.getKey(), e.getValue()); } } @Override public synchronized void clear() { keys.clear(); values.clear(); } private void enqueue(K key, V value) { if (key == null) throw new IllegalArgumentException(); if (keys.add(key)) { values.put(key, value); } } private final Queue<K> keys = new LinkedList<>(); private final Map<K, V> values = new HashMap<>(); }