Last active
November 24, 2018 21:53
-
-
Save JarvisCraft/f0a03f37f755f00810d55a6a6cb6550f to your computer and use it in GitHub Desktop.
MapUtil for Java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ru.progrm_jarvis.minecraft.fakeentitylib.util; | |
import lombok.AccessLevel; | |
import lombok.NonNull; | |
import lombok.RequiredArgsConstructor; | |
import lombok.experimental.FieldDefaults; | |
import lombok.experimental.UtilityClass; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.Map; | |
import java.util.Set; | |
import java.util.concurrent.locks.Lock; | |
import java.util.concurrent.locks.ReadWriteLock; | |
import java.util.concurrent.locks.ReentrantReadWriteLock; | |
import java.util.function.BiConsumer; | |
import java.util.function.BiFunction; | |
import java.util.function.Function; | |
/** | |
* An utility for {@link java.util.Map} manipulations. | |
*/ | |
@UtilityClass | |
public class MapUtil { | |
public <K, V> Map<K, V> concurrentMap(@NonNull final Map<K, V> map) { | |
return new LockedMap<>(map); | |
} | |
@RequiredArgsConstructor | |
@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) | |
private static final class LockedMap<K, V> implements Map<K, V> { | |
Map<K, V> map; | |
ReadWriteLock lock = new ReentrantReadWriteLock(); | |
Lock readLock = lock.readLock(); | |
Lock writeLock = lock.writeLock(); | |
@Override | |
public int size() { | |
readLock.lock(); | |
try { | |
return map.size(); | |
} finally { | |
readLock.unlock(); | |
} | |
} | |
@Override | |
public boolean isEmpty() { | |
readLock.lock(); | |
try { | |
return map.isEmpty(); | |
} finally { | |
readLock.unlock(); | |
} | |
} | |
@Override | |
public boolean containsKey(final Object key) { | |
readLock.lock(); | |
try { | |
return map.containsKey(key); | |
} finally { | |
readLock.unlock(); | |
} | |
} | |
@Override | |
public boolean containsValue(final Object value) { | |
readLock.lock(); | |
try { | |
return map.containsValue(value); | |
} finally { | |
readLock.unlock(); | |
} | |
} | |
@Override | |
public V get(final Object key) { | |
readLock.lock(); | |
try { | |
return map.get(key); | |
} finally { | |
readLock.unlock(); | |
} | |
} | |
@Override | |
public V put(final K key, final V value) { | |
writeLock.lock(); | |
try { | |
return map.put(key,value); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public V remove(final Object key) { | |
writeLock.lock(); | |
try { | |
return map.remove(key); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public void putAll(final Map<? extends K, ? extends V> m) { | |
writeLock.lock(); | |
try { | |
map.putAll(m); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public void clear() { | |
writeLock.lock(); | |
try { | |
map.clear(); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public Set<K> keySet() { | |
readLock.lock(); | |
try { | |
return map.keySet(); | |
} finally { | |
readLock.unlock(); | |
} | |
} | |
@Override | |
public Collection<V> values() { | |
readLock.lock(); | |
try { | |
return map.values(); | |
} finally { | |
readLock.unlock(); | |
} | |
} | |
@Override | |
public Set<Entry<K, V>> entrySet() { | |
readLock.lock(); | |
try { | |
return map.entrySet(); | |
} finally { | |
readLock.unlock(); | |
} | |
} | |
@Override | |
public V getOrDefault(final Object key, final V defaultValue) { | |
readLock.lock(); | |
try { | |
return map.getOrDefault(key,defaultValue); | |
} finally { | |
readLock.unlock(); | |
} | |
} | |
@Override | |
public void forEach(final BiConsumer<? super K, ? super V> action) { | |
readLock.lock(); | |
try { | |
map.forEach(action); | |
} finally { | |
readLock.unlock(); | |
} | |
} | |
@Override | |
public void replaceAll(final BiFunction<? super K, ? super V, ? extends V> function) { | |
writeLock.lock(); | |
try { | |
map.replaceAll(function); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public V putIfAbsent(final K key, final V value) { | |
writeLock.lock(); | |
try { | |
return map.putIfAbsent(key,value); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public boolean remove(final Object key, final Object value) { | |
writeLock.lock(); | |
try { | |
return map.remove(key,value); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public boolean replace(final K key, final V oldValue, final V newValue) { | |
writeLock.lock(); | |
try { | |
return map.replace(key,oldValue, newValue); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public V replace(final K key, final V value) { | |
writeLock.lock(); | |
try { | |
return map.replace(key,value); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public V computeIfAbsent(final K key, Function<? super K, ? extends V> mappingFunction) { | |
writeLock.lock(); | |
try { | |
return map.computeIfAbsent(key,mappingFunction); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public V computeIfPresent(final K key, final BiFunction<? super K, ? super V, ? extends V> remappingFunction) { | |
writeLock.lock(); | |
try { | |
return map.computeIfPresent(key,remappingFunction); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public V compute(final K key, final BiFunction<? super K, ? super V, ? extends V> remappingFunction) { | |
writeLock.lock(); | |
try { | |
return map.compute(key,remappingFunction); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public V merge(final K key, final V value, | |
final BiFunction<? super V, ? super V, ? extends V> remappingFunction) { | |
writeLock.lock(); | |
try { | |
return map.merge(key, value, remappingFunction); | |
} finally { | |
writeLock.unlock(); | |
} | |
} | |
@Override | |
public String toString() { | |
return "Concurrent" + map.toString(); | |
} | |
@Override | |
public int hashCode() { | |
return map.hashCode(); | |
} | |
@Override | |
public boolean equals(final Object obj) { | |
if (obj == null) return false; | |
if (obj == this) return true; | |
// if also LockedMap then compare by backend map (no worries about extending classes as it is final <3) | |
if (obj instanceof LockedMap) return map.equals(((LockedMap) obj).map); | |
return map.equals(obj); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment