create ConcurrentMultiMap, remove unused map

This commit is contained in:
Anthony Calosa
2024-11-15 20:24:20 +08:00
parent d9c4c818b5
commit f52b7abe61
4 changed files with 140 additions and 213 deletions

View File

@@ -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>

View File

@@ -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;
}*/
}

View File

@@ -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;
}
}
}

View File

@@ -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;
} }
} }