mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
create ConcurrentMultiMap, remove unused map
This commit is contained in:
@@ -18,11 +18,6 @@
|
|||||||
<artifactId>guava</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>33.3.1-android</version>
|
<version>33.3.1-android</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-collections4</artifactId>
|
|
||||||
<version>4.5.0-M2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package forge.util.collect;
|
||||||
|
|
||||||
|
import com.google.common.collect.ConcurrentHashMultiset;
|
||||||
|
import com.google.common.collect.Multiset;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
|
public class ConcurrentMultiMap<K, V> {
|
||||||
|
private Map<K, Collection<V>> _MAP;
|
||||||
|
private Map<K, Collection<V>> MAP() {
|
||||||
|
Map<K, Collection<V>> result = _MAP;
|
||||||
|
if (result == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
result = _MAP;
|
||||||
|
if (result == null) {
|
||||||
|
result = new ConcurrentHashMap<>();
|
||||||
|
_MAP = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _MAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return MAP().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return MAP().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("SuspiciousMethodCalls")
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
if (key == null)
|
||||||
|
return false;
|
||||||
|
return MAP().containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean put(K key, V value) {
|
||||||
|
return safeGet(key).add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("SuspiciousMethodCalls")
|
||||||
|
public boolean remove(Object key, Object value) {
|
||||||
|
if (key == null || value == null)
|
||||||
|
return false;
|
||||||
|
return MAP().get(key).remove(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean putAll(K key, Iterable<? extends V> iterable) {
|
||||||
|
Collection<V> values = safeGet(key);
|
||||||
|
for (V v : iterable) {
|
||||||
|
if(!values.add(v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean putAll(Map<? extends K, ? extends V> map) {
|
||||||
|
for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
|
||||||
|
if(!safeGet(entry.getKey()).add(entry.getValue())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
MAP().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<V> safeGet(K key) {
|
||||||
|
return MAP().computeIfAbsent(key, value -> new ConcurrentLinkedQueue<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<V> get(K key) {
|
||||||
|
return MAP().get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<K> keySet() {
|
||||||
|
return MAP().keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Multiset<K> keys() {
|
||||||
|
Multiset<K> multiset = ConcurrentHashMultiset.create();
|
||||||
|
multiset.addAll(MAP().keySet());
|
||||||
|
return multiset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<V> values() {
|
||||||
|
Queue<V> values = new ConcurrentLinkedQueue<>();
|
||||||
|
for (Map.Entry<K, Collection<V>> entry : MAP().entrySet()) {
|
||||||
|
values.addAll(entry.getValue());
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*@SuppressWarnings("SuspiciousMethodCalls")
|
||||||
|
public boolean containsValue(Object value) {
|
||||||
|
if (value == null)
|
||||||
|
return false;
|
||||||
|
return storage.containsValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsEntry(Object key, Object value) {
|
||||||
|
if (key == null || value == null)
|
||||||
|
return false;
|
||||||
|
return storage.entrySet().contains(Maps.immutableEntry(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<V> replaceValues(K key, Iterable<? extends V> values) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<V> removeAll(Object key) {
|
||||||
|
if (key == null)
|
||||||
|
return null;
|
||||||
|
return storage.containsKey(key) ? storage.remove(key) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Map.Entry<K, V>> entries() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<K, Collection<V>> asMap() {
|
||||||
|
return null;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
@@ -1,204 +0,0 @@
|
|||||||
package forge.util.collect;
|
|
||||||
|
|
||||||
import org.apache.commons.collections4.MapIterator;
|
|
||||||
import org.apache.commons.collections4.MultiSet;
|
|
||||||
import org.apache.commons.collections4.MultiValuedMap;
|
|
||||||
import org.apache.commons.collections4.map.HashedMap;
|
|
||||||
import org.apache.commons.collections4.multiset.HashMultiSet;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
|
|
||||||
public class ConcurrentMultiValuedMap<K,V> implements MultiValuedMap<K,V> {
|
|
||||||
|
|
||||||
private Map<K, Collection<V>> storage = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return storage.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return storage.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsKey(Object o) {
|
|
||||||
//noinspection SuspiciousMethodCalls
|
|
||||||
return storage.containsKey(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsValue(Object o) {
|
|
||||||
//noinspection SuspiciousMethodCalls
|
|
||||||
return storage.containsValue(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsMapping(Object key, Object value) {
|
|
||||||
@SuppressWarnings("SuspiciousMethodCalls")
|
|
||||||
Collection<V> values = storage.get(key);
|
|
||||||
if(values==null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (V v : values) {
|
|
||||||
if(v.equals(value)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<V> get(K k) {
|
|
||||||
return storage.get(k);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Collection<V> safeGet(K key) {
|
|
||||||
return storage.computeIfAbsent(key, value -> new ConcurrentLinkedQueue<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean put(K k, V v) {
|
|
||||||
return safeGet(k).add(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean putAll(K k, Iterable<? extends V> iterable) {
|
|
||||||
Collection<V> values = safeGet(k);
|
|
||||||
for (V v : iterable) {
|
|
||||||
if(!values.add(v)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean putAll(Map<? extends K, ? extends V> map) {
|
|
||||||
for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
|
|
||||||
if(!safeGet(entry.getKey()).add(entry.getValue())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean putAll(MultiValuedMap<? extends K, ? extends V> multiValuedMap) {
|
|
||||||
MapIterator<? extends K, ? extends V> iterator = multiValuedMap.mapIterator();
|
|
||||||
while(iterator.hasNext()) {
|
|
||||||
if(!safeGet(iterator.getKey()).add(iterator.getValue())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<V> remove(Object o) {
|
|
||||||
//noinspection SuspiciousMethodCalls
|
|
||||||
return storage.remove(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("SuspiciousMethodCalls")
|
|
||||||
@Override
|
|
||||||
public boolean removeMapping(Object o, Object v) {
|
|
||||||
Collection<V> values = storage.get(o);
|
|
||||||
return values != null && values.remove(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
storage.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<Map.Entry<K, V>> entries() {
|
|
||||||
Collection<Map.Entry<K, V>> collection = new LinkedList<>();
|
|
||||||
collectValues((k,v)->{
|
|
||||||
Map.Entry<K,V> mapEntry = new TempMapEntry(k, v);
|
|
||||||
collection.add(mapEntry);
|
|
||||||
});
|
|
||||||
return collection;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MultiSet<K> keys() {
|
|
||||||
MultiSet<K> multiSet = new HashMultiSet<>();
|
|
||||||
multiSet.addAll(storage.keySet());
|
|
||||||
return multiSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<K> keySet() {
|
|
||||||
return storage.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<V> values() {
|
|
||||||
List<V> values = new LinkedList<>();
|
|
||||||
for (Map.Entry<K, Collection<V>> entry : storage.entrySet()) {
|
|
||||||
for (V v : entry.getValue()) {
|
|
||||||
values.add(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<K, Collection<V>> asMap() {
|
|
||||||
return Collections.unmodifiableMap(storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MapIterator<K, V> mapIterator() {
|
|
||||||
HashedMap<K,V> hashedMap = new HashedMap<>();
|
|
||||||
collectValues(hashedMap::put);
|
|
||||||
return hashedMap.mapIterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void collectValues(BiConsumer<K,V> consumer) {
|
|
||||||
for (Map.Entry<K, Collection<V>> entry : storage.entrySet()) {
|
|
||||||
for (V v : entry.getValue()) {
|
|
||||||
consumer.accept(entry.getKey(), v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class TempMapEntry implements Map.Entry<K,V> {
|
|
||||||
|
|
||||||
private V val;
|
|
||||||
private final K key;
|
|
||||||
|
|
||||||
TempMapEntry(K key, V value) {
|
|
||||||
this.val = value;
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public K getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public V getValue() {
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public V setValue(V value) {
|
|
||||||
V old = val;
|
|
||||||
val = value;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -42,6 +42,7 @@ import forge.game.replacement.ReplacementType;
|
|||||||
import forge.game.spellability.AbilityManaPart;
|
import forge.game.spellability.AbilityManaPart;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.staticability.StaticAbilityUnspentMana;
|
import forge.game.staticability.StaticAbilityUnspentMana;
|
||||||
|
import forge.util.collect.ConcurrentMultiMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -53,14 +54,14 @@ import forge.game.staticability.StaticAbilityUnspentMana;
|
|||||||
*/
|
*/
|
||||||
public class ManaPool extends ManaConversionMatrix implements Iterable<Mana> {
|
public class ManaPool extends ManaConversionMatrix implements Iterable<Mana> {
|
||||||
private final Player owner;
|
private final Player owner;
|
||||||
private Multimap<Byte, Mana> _floatingMana;
|
private ConcurrentMultiMap<Byte, Mana> _floatingMana;
|
||||||
private Multimap<Byte, Mana> floatingMana() {
|
private ConcurrentMultiMap<Byte, Mana> floatingMana() {
|
||||||
Multimap<Byte, Mana> result = _floatingMana;
|
ConcurrentMultiMap<Byte, Mana> result = _floatingMana;
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
result = _floatingMana;
|
result = _floatingMana;
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
result = Multimaps.synchronizedMultimap(ArrayListMultimap.create());
|
result = new ConcurrentMultiMap<>();
|
||||||
_floatingMana = result;
|
_floatingMana = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user