You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/08/30 15:10:50 UTC
[commons-beanutils] branch master updated: Update provenance as comment.
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-beanutils.git
The following commit(s) were added to refs/heads/master by this push:
new bf4ccba1 Update provenance as comment.
bf4ccba1 is described below
commit bf4ccba1e9201a49f568e8d10a1e359002989105
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Tue Aug 30 11:10:45 2022 -0400
Update provenance as comment.
---
.../apache/commons/beanutils2/WeakFastHashMap.java | 1493 ++++++++++----------
1 file changed, 747 insertions(+), 746 deletions(-)
diff --git a/src/main/java/org/apache/commons/beanutils2/WeakFastHashMap.java b/src/main/java/org/apache/commons/beanutils2/WeakFastHashMap.java
index b9324df0..9bbe8c5c 100644
--- a/src/main/java/org/apache/commons/beanutils2/WeakFastHashMap.java
+++ b/src/main/java/org/apache/commons/beanutils2/WeakFastHashMap.java
@@ -1,746 +1,747 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.beanutils2;
-
-import java.util.Collection;
-import java.util.ConcurrentModificationException;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.WeakHashMap;
-
-/**
- * <p>A customized implementation of {@code java.util.HashMap} designed
- * to operate in a multi-threaded environment where the large majority of
- * method calls are read-only, instead of structural changes. When operating
- * in "fast" mode, read calls are non-synchronized and write calls perform the
- * following steps:</p>
- * <ul>
- * <li>Clone the existing collection
- * <li>Perform the modification on the clone
- * <li>Replace the existing collection with the (modified) clone
- * </ul>
- * <p>When first created, objects of this class default to "slow" mode, where
- * all accesses of any type are synchronized but no cloning takes place. This
- * is appropriate for initially populating the collection, followed by a switch
- * to "fast" mode (by calling {@code setFast(true)}) after initialization
- * is complete.</p>
- *
- * <p><strong>NOTE</strong>: If you are creating and accessing a
- * {@code HashMap} only within a single thread, you should use
- * {@code java.util.HashMap} directly (with no synchronization), for
- * maximum performance.</p>
- *
- * <p><strong>NOTE</strong>: <i>This class is not cross-platform.
- * Using it may cause unexpected failures on some architectures.</i>
- * It suffers from the same problems as the double-checked locking idiom.
- * In particular, the instruction that clones the internal collection and the
- * instruction that sets the internal reference to the clone can be executed
- * or perceived out-of-order. This means that any read operation might fail
- * unexpectedly, as it may be reading the state of the internal collection
- * before the internal collection is fully formed.
- * For more information on the double-checked locking idiom, see the
- * <a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">
- * Double-Checked Locking Idiom Is Broken Declaration</a>.</p>
- *
- * @since Commons Collections 1.0
- * @param <K> the key
- * @param <V> the value
- */
-public class WeakFastHashMap<K, V> extends HashMap<K, V> {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * The underlying map we are managing.
- */
- private volatile Map<K, V> map;
-
- /**
- * Are we currently operating in "fast" mode?
- */
- private boolean fast;
-
- // Constructors
-
-
- /**
- * Constructs an empty map.
- */
- public WeakFastHashMap() {
- this.map = createMap();
- }
-
- /**
- * Constructs an empty map with the specified capacity.
- *
- * @param capacity the initial capacity of the empty map
- */
- public WeakFastHashMap(final int capacity) {
- this.map = createMap(capacity);
- }
-
- /**
- * Constructs an empty map with the specified capacity and load factor.
- *
- * @param capacity the initial capacity of the empty map
- * @param factor the load factor of the new map
- */
- public WeakFastHashMap(final int capacity, final float factor) {
- this.map = createMap(capacity, factor);
- }
-
- /**
- * Constructs a new map with the same mappings as the specified map.
- *
- * @param map the map whose mappings are to be copied
- */
- public WeakFastHashMap(final Map<? extends K, ? extends V> map) {
- this.map = createMap(map);
- }
-
- // Property access
-
-
- /**
- * Returns true if this map is operating in fast mode.
- *
- * @return true if this map is operating in fast mode
- */
- public boolean getFast() {
- return this.fast;
- }
-
- /**
- * Sets whether this map is operating in fast mode.
- *
- * @param fast true if this map should operate in fast mode
- */
- public void setFast(final boolean fast) {
- this.fast = fast;
- }
-
- // Map access
-
- // These methods can forward straight to the wrapped Map in 'fast' mode.
- // (because they are query methods)
-
- /**
- * Gets the value to which this map maps the specified key. Returns
- * {@code null} if the map contains no mapping for this key, or if
- * there is a mapping with a value of {@code null}. Use the
- * {@code containsKey()} method to disambiguate these cases.
- *
- * @param key the key whose value is to be returned
- * @return the value mapped to that key, or null
- */
- @Override
- public V get(final Object key) {
- if (fast) {
- return map.get(key);
- }
- synchronized (map) {
- return map.get(key);
- }
- }
-
- /**
- * Gets the number of key-value mappings in this map.
- *
- * @return the current size of the map
- */
- @Override
- public int size() {
- if (fast) {
- return map.size();
- }
- synchronized (map) {
- return map.size();
- }
- }
-
- /**
- * Gets {@code true} if this map contains no mappings.
- *
- * @return is the map currently empty
- */
- @Override
- public boolean isEmpty() {
- if (fast) {
- return map.isEmpty();
- }
- synchronized (map) {
- return map.isEmpty();
- }
- }
-
- /**
- * Gets {@code true} if this map contains a mapping for the
- * specified key.
- *
- * @param key the key to be searched for
- * @return true if the map contains the key
- */
- @Override
- public boolean containsKey(final Object key) {
- if (fast) {
- return map.containsKey(key);
- }
- synchronized (map) {
- return map.containsKey(key);
- }
- }
-
- /**
- * Gets {@code true} if this map contains one or more keys mapping
- * to the specified value.
- *
- * @param value the value to be searched for
- * @return true if the map contains the value
- */
- @Override
- public boolean containsValue(final Object value) {
- if (fast) {
- return map.containsValue(value);
- }
- synchronized (map) {
- return map.containsValue(value);
- }
- }
-
- // Map modification
-
- // These methods perform special behavior in 'fast' mode.
- // The map is cloned, updated and then assigned back.
- // See the comments at the top as to why this won't always work.
-
- /**
- * Associate the specified value with the specified key in this map.
- * If the map previously contained a mapping for this key, the old
- * value is replaced and returned.
- *
- * @param key the key with which the value is to be associated
- * @param value the value to be associated with this key
- * @return the value previously mapped to the key, or null
- */
- @Override
- public V put(final K key, final V value) {
- if (fast) {
- synchronized (this) {
- final Map<K, V> temp = cloneMap(map);
- final V result = temp.put(key, value);
- map = temp;
- return result;
- }
- }
- synchronized (map) {
- return map.put(key, value);
- }
- }
-
- /**
- * Copy all of the mappings from the specified map to this one, replacing
- * any mappings with the same keys.
- *
- * @param in the map whose mappings are to be copied
- */
- @Override
- public void putAll(final Map<? extends K, ? extends V> in) {
- if (fast) {
- synchronized (this) {
- final Map<K, V> temp = cloneMap(map);
- temp.putAll(in);
- map = temp;
- }
- } else {
- synchronized (map) {
- map.putAll(in);
- }
- }
- }
-
- /**
- * Remove any mapping for this key, and return any previously
- * mapped value.
- *
- * @param key the key whose mapping is to be removed
- * @return the value removed, or null
- */
- @Override
- public V remove(final Object key) {
- if (fast) {
- synchronized (this) {
- final Map<K, V> temp = cloneMap(map);
- final V result = temp.remove(key);
- map = temp;
- return result;
- }
- }
- synchronized (map) {
- return map.remove(key);
- }
- }
-
- /**
- * Remove all mappings from this map.
- */
- @Override
- public void clear() {
- if (fast) {
- synchronized (this) {
- map = createMap();
- }
- } else {
- synchronized (map) {
- map.clear();
- }
- }
- }
-
- // Basic object methods
-
-
- /**
- * Compare the specified object with this list for equality. This
- * implementation uses exactly the code that is used to define the
- * list equals function in the documentation for the
- * {@code Map.equals} method.
- *
- * @param o the object to be compared to this list
- * @return true if the two maps are equal
- */
- @Override
- public boolean equals(final Object o) {
- // Simple tests that require no synchronization
- if (o == this) {
- return true;
- }
- if (!(o instanceof Map)) {
- return false;
- }
- final Map<?, ?> mo = (Map<?, ?>) o;
-
- // Compare the two maps for equality
- if (fast) {
- if (mo.size() != map.size()) {
- return false;
- }
- for (final Map.Entry<K, V> e : map.entrySet()) {
- final K key = e.getKey();
- final V value = e.getValue();
- if (value == null) {
- if (!(mo.get(key) == null && mo.containsKey(key))) {
- return false;
- }
- } else if (!value.equals(mo.get(key))) {
- return false;
- }
- }
- return true;
-
- }
- synchronized (map) {
- if (mo.size() != map.size()) {
- return false;
- }
- for (final Map.Entry<K, V> e : map.entrySet()) {
- final K key = e.getKey();
- final V value = e.getValue();
- if (value == null) {
- if (!(mo.get(key) == null && mo.containsKey(key))) {
- return false;
- }
- } else if (!value.equals(mo.get(key))) {
- return false;
- }
- }
- return true;
- }
- }
-
- /**
- * Gets the hash code value for this map. This implementation uses
- * exactly the code that is used to define the list hash function in the
- * documentation for the {@code Map.hashCode} method.
- *
- * @return suitable integer hash code
- */
- @Override
- public int hashCode() {
- if (fast) {
- int h = 0;
- for (final Map.Entry<K, V> e : map.entrySet()) {
- h += e.hashCode();
- }
- return h;
- }
- synchronized (map) {
- int h = 0;
- for (final Map.Entry<K, V> e : map.entrySet()) {
- h += e.hashCode();
- }
- return h;
- }
- }
-
- /**
- * Gets a shallow copy of this {@code FastHashMap} instance.
- * The keys and values themselves are not copied.
- *
- * @return a clone of this map
- */
- @Override
- public Object clone() {
- WeakFastHashMap<K, V> results = null;
- if (fast) {
- results = new WeakFastHashMap<>(map);
- } else {
- synchronized (map) {
- results = new WeakFastHashMap<>(map);
- }
- }
- results.setFast(getFast());
- return results;
- }
-
- // Map views
-
-
- /**
- * Gets a collection view of the mappings contained in this map. Each
- * element in the returned collection is a {@code Map.Entry}.
- * @return the set of map Map entries
- */
- @Override
- public Set<Map.Entry<K, V>> entrySet() {
- return new EntrySet();
- }
-
- /**
- * Gets a set view of the keys contained in this map.
- * @return the set of the Map's keys
- */
- @Override
- public Set<K> keySet() {
- return new KeySet();
- }
-
- /**
- * Gets a collection view of the values contained in this map.
- * @return the set of the Map's values
- */
- @Override
- public Collection<V> values() {
- return new Values();
- }
-
- // Abstractions on Map creations (for subclasses such as WeakFastHashMap)
-
-
- protected Map<K, V> createMap() {
- return new WeakHashMap<>();
- }
-
- protected Map<K, V> createMap(final int capacity) {
- return new WeakHashMap<>(capacity);
- }
-
- protected Map<K, V> createMap(final int capacity, final float factor) {
- return new WeakHashMap<>(capacity, factor);
- }
-
- protected Map<K, V> createMap(final Map<? extends K, ? extends V> map) {
- return new WeakHashMap<>(map);
- }
-
- protected Map<K, V> cloneMap(final Map<? extends K, ? extends V> map) {
- return createMap(map);
- }
-
- // Map view inner classes
-
- /**
- * Abstract collection implementation shared by keySet(), values() and entrySet().
- *
- * @param <E> the element type
- */
- private abstract class CollectionView<E> implements Collection<E> {
-
- public CollectionView() {
- }
-
- protected abstract Collection<E> get(Map<K, V> map);
- protected abstract E iteratorNext(Map.Entry<K, V> entry);
-
- @Override
- public void clear() {
- if (fast) {
- synchronized (WeakFastHashMap.this) {
- map = createMap();
- }
- } else {
- synchronized (map) {
- get(map).clear();
- }
- }
- }
-
- @Override
- public boolean remove(final Object o) {
- if (fast) {
- synchronized (WeakFastHashMap.this) {
- final Map<K, V> temp = cloneMap(map);
- final boolean r = get(temp).remove(o);
- map = temp;
- return r;
- }
- }
- synchronized (map) {
- return get(map).remove(o);
- }
- }
-
- @Override
- public boolean removeAll(final Collection<?> o) {
- if (fast) {
- synchronized (WeakFastHashMap.this) {
- final Map<K, V> temp = cloneMap(map);
- final boolean r = get(temp).removeAll(o);
- map = temp;
- return r;
- }
- }
- synchronized (map) {
- return get(map).removeAll(o);
- }
- }
-
- @Override
- public boolean retainAll(final Collection<?> o) {
- if (fast) {
- synchronized (WeakFastHashMap.this) {
- final Map<K, V> temp = cloneMap(map);
- final boolean r = get(temp).retainAll(o);
- map = temp;
- return r;
- }
- }
- synchronized (map) {
- return get(map).retainAll(o);
- }
- }
-
- @Override
- public int size() {
- if (fast) {
- return get(map).size();
- }
- synchronized (map) {
- return get(map).size();
- }
- }
-
- @Override
- public boolean isEmpty() {
- if (fast) {
- return get(map).isEmpty();
- }
- synchronized (map) {
- return get(map).isEmpty();
- }
- }
-
- @Override
- public boolean contains(final Object o) {
- if (fast) {
- return get(map).contains(o);
- }
- synchronized (map) {
- return get(map).contains(o);
- }
- }
-
- @Override
- public boolean containsAll(final Collection<?> o) {
- if (fast) {
- return get(map).containsAll(o);
- }
- synchronized (map) {
- return get(map).containsAll(o);
- }
- }
-
- @Override
- public <T> T[] toArray(final T[] o) {
- if (fast) {
- return get(map).toArray(o);
- }
- synchronized (map) {
- return get(map).toArray(o);
- }
- }
-
- @Override
- public Object[] toArray() {
- if (fast) {
- return get(map).toArray();
- }
- synchronized (map) {
- return get(map).toArray();
- }
- }
-
- @Override
- public boolean equals(final Object o) {
- if (o == this) {
- return true;
- }
- if (fast) {
- return get(map).equals(o);
- }
- synchronized (map) {
- return get(map).equals(o);
- }
- }
-
- @Override
- public int hashCode() {
- if (fast) {
- return get(map).hashCode();
- }
- synchronized (map) {
- return get(map).hashCode();
- }
- }
-
- @Override
- public boolean add(final E o) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean addAll(final Collection<? extends E> c) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Iterator<E> iterator() {
- return new CollectionViewIterator();
- }
-
- private class CollectionViewIterator implements Iterator<E> {
-
- private Map<K, V> expected;
- private Map.Entry<K, V> lastReturned;
- private final Iterator<Map.Entry<K, V>> iterator;
-
- public CollectionViewIterator() {
- this.expected = map;
- this.iterator = expected.entrySet().iterator();
- }
-
- @Override
- public boolean hasNext() {
- if (expected != map) {
- throw new ConcurrentModificationException();
- }
- return iterator.hasNext();
- }
-
- @Override
- public E next() {
- if (expected != map) {
- throw new ConcurrentModificationException();
- }
- lastReturned = iterator.next();
- return iteratorNext(lastReturned);
- }
-
- @Override
- public void remove() {
- if (lastReturned == null) {
- throw new IllegalStateException();
- }
- if (fast) {
- synchronized (WeakFastHashMap.this) {
- if (expected != map) {
- throw new ConcurrentModificationException();
- }
- WeakFastHashMap.this.remove(lastReturned.getKey());
- lastReturned = null;
- expected = map;
- }
- } else {
- iterator.remove();
- lastReturned = null;
- }
- }
- }
- }
-
- /**
- * Sets implementation over the keys of the FastHashMap
- */
- private class KeySet extends CollectionView<K> implements Set<K> {
-
- @Override
- protected Collection<K> get(final Map<K, V> map) {
- return map.keySet();
- }
-
- @Override
- protected K iteratorNext(final Map.Entry<K, V> entry) {
- return entry.getKey();
- }
-
- }
-
- /**
- * Collection implementation over the values of the FastHashMap
- */
- private class Values extends CollectionView<V> {
-
- @Override
- protected Collection<V> get(final Map<K, V> map) {
- return map.values();
- }
-
- @Override
- protected V iteratorNext(final Map.Entry<K, V> entry) {
- return entry.getValue();
- }
- }
-
- /**
- * Sets implementation over the entries of the FastHashMap
- */
- private class EntrySet extends CollectionView<Map.Entry<K, V>> implements Set<Map.Entry<K, V>> {
-
- @Override
- protected Collection<Map.Entry<K, V>> get(final Map<K, V> map) {
- return map.entrySet();
- }
-
- @Override
- protected Map.Entry<K, V> iteratorNext(final Map.Entry<K, V> entry) {
- return entry;
- }
-
- }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.beanutils2;
+
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+/**
+ * <p>A customized implementation of {@code java.util.HashMap} designed
+ * to operate in a multi-threaded environment where the large majority of
+ * method calls are read-only, instead of structural changes. When operating
+ * in "fast" mode, read calls are non-synchronized and write calls perform the
+ * following steps:</p>
+ * <ul>
+ * <li>Clone the existing collection
+ * <li>Perform the modification on the clone
+ * <li>Replace the existing collection with the (modified) clone
+ * </ul>
+ * <p>When first created, objects of this class default to "slow" mode, where
+ * all accesses of any type are synchronized but no cloning takes place. This
+ * is appropriate for initially populating the collection, followed by a switch
+ * to "fast" mode (by calling {@code setFast(true)}) after initialization
+ * is complete.</p>
+ *
+ * <p><strong>NOTE</strong>: If you are creating and accessing a
+ * {@code HashMap} only within a single thread, you should use
+ * {@code java.util.HashMap} directly (with no synchronization), for
+ * maximum performance.</p>
+ *
+ * <p><strong>NOTE</strong>: <i>This class is not cross-platform.
+ * Using it may cause unexpected failures on some architectures.</i>
+ * It suffers from the same problems as the double-checked locking idiom.
+ * In particular, the instruction that clones the internal collection and the
+ * instruction that sets the internal reference to the clone can be executed
+ * or perceived out-of-order. This means that any read operation might fail
+ * unexpectedly, as it may be reading the state of the internal collection
+ * before the internal collection is fully formed.
+ * For more information on the double-checked locking idiom, see the
+ * <a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">
+ * Double-Checked Locking Idiom Is Broken Declaration</a>.</p>
+ *
+ * Copied from Commons Collections 1.0
+ *
+ * @param <K> the key
+ * @param <V> the value
+ */
+public class WeakFastHashMap<K, V> extends HashMap<K, V> {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The underlying map we are managing.
+ */
+ private volatile Map<K, V> map;
+
+ /**
+ * Are we currently operating in "fast" mode?
+ */
+ private boolean fast;
+
+ // Constructors
+
+
+ /**
+ * Constructs an empty map.
+ */
+ public WeakFastHashMap() {
+ this.map = createMap();
+ }
+
+ /**
+ * Constructs an empty map with the specified capacity.
+ *
+ * @param capacity the initial capacity of the empty map
+ */
+ public WeakFastHashMap(final int capacity) {
+ this.map = createMap(capacity);
+ }
+
+ /**
+ * Constructs an empty map with the specified capacity and load factor.
+ *
+ * @param capacity the initial capacity of the empty map
+ * @param factor the load factor of the new map
+ */
+ public WeakFastHashMap(final int capacity, final float factor) {
+ this.map = createMap(capacity, factor);
+ }
+
+ /**
+ * Constructs a new map with the same mappings as the specified map.
+ *
+ * @param map the map whose mappings are to be copied
+ */
+ public WeakFastHashMap(final Map<? extends K, ? extends V> map) {
+ this.map = createMap(map);
+ }
+
+ // Property access
+
+
+ /**
+ * Returns true if this map is operating in fast mode.
+ *
+ * @return true if this map is operating in fast mode
+ */
+ public boolean getFast() {
+ return this.fast;
+ }
+
+ /**
+ * Sets whether this map is operating in fast mode.
+ *
+ * @param fast true if this map should operate in fast mode
+ */
+ public void setFast(final boolean fast) {
+ this.fast = fast;
+ }
+
+ // Map access
+
+ // These methods can forward straight to the wrapped Map in 'fast' mode.
+ // (because they are query methods)
+
+ /**
+ * Gets the value to which this map maps the specified key. Returns
+ * {@code null} if the map contains no mapping for this key, or if
+ * there is a mapping with a value of {@code null}. Use the
+ * {@code containsKey()} method to disambiguate these cases.
+ *
+ * @param key the key whose value is to be returned
+ * @return the value mapped to that key, or null
+ */
+ @Override
+ public V get(final Object key) {
+ if (fast) {
+ return map.get(key);
+ }
+ synchronized (map) {
+ return map.get(key);
+ }
+ }
+
+ /**
+ * Gets the number of key-value mappings in this map.
+ *
+ * @return the current size of the map
+ */
+ @Override
+ public int size() {
+ if (fast) {
+ return map.size();
+ }
+ synchronized (map) {
+ return map.size();
+ }
+ }
+
+ /**
+ * Gets {@code true} if this map contains no mappings.
+ *
+ * @return is the map currently empty
+ */
+ @Override
+ public boolean isEmpty() {
+ if (fast) {
+ return map.isEmpty();
+ }
+ synchronized (map) {
+ return map.isEmpty();
+ }
+ }
+
+ /**
+ * Gets {@code true} if this map contains a mapping for the
+ * specified key.
+ *
+ * @param key the key to be searched for
+ * @return true if the map contains the key
+ */
+ @Override
+ public boolean containsKey(final Object key) {
+ if (fast) {
+ return map.containsKey(key);
+ }
+ synchronized (map) {
+ return map.containsKey(key);
+ }
+ }
+
+ /**
+ * Gets {@code true} if this map contains one or more keys mapping
+ * to the specified value.
+ *
+ * @param value the value to be searched for
+ * @return true if the map contains the value
+ */
+ @Override
+ public boolean containsValue(final Object value) {
+ if (fast) {
+ return map.containsValue(value);
+ }
+ synchronized (map) {
+ return map.containsValue(value);
+ }
+ }
+
+ // Map modification
+
+ // These methods perform special behavior in 'fast' mode.
+ // The map is cloned, updated and then assigned back.
+ // See the comments at the top as to why this won't always work.
+
+ /**
+ * Associate the specified value with the specified key in this map.
+ * If the map previously contained a mapping for this key, the old
+ * value is replaced and returned.
+ *
+ * @param key the key with which the value is to be associated
+ * @param value the value to be associated with this key
+ * @return the value previously mapped to the key, or null
+ */
+ @Override
+ public V put(final K key, final V value) {
+ if (fast) {
+ synchronized (this) {
+ final Map<K, V> temp = cloneMap(map);
+ final V result = temp.put(key, value);
+ map = temp;
+ return result;
+ }
+ }
+ synchronized (map) {
+ return map.put(key, value);
+ }
+ }
+
+ /**
+ * Copy all of the mappings from the specified map to this one, replacing
+ * any mappings with the same keys.
+ *
+ * @param in the map whose mappings are to be copied
+ */
+ @Override
+ public void putAll(final Map<? extends K, ? extends V> in) {
+ if (fast) {
+ synchronized (this) {
+ final Map<K, V> temp = cloneMap(map);
+ temp.putAll(in);
+ map = temp;
+ }
+ } else {
+ synchronized (map) {
+ map.putAll(in);
+ }
+ }
+ }
+
+ /**
+ * Remove any mapping for this key, and return any previously
+ * mapped value.
+ *
+ * @param key the key whose mapping is to be removed
+ * @return the value removed, or null
+ */
+ @Override
+ public V remove(final Object key) {
+ if (fast) {
+ synchronized (this) {
+ final Map<K, V> temp = cloneMap(map);
+ final V result = temp.remove(key);
+ map = temp;
+ return result;
+ }
+ }
+ synchronized (map) {
+ return map.remove(key);
+ }
+ }
+
+ /**
+ * Remove all mappings from this map.
+ */
+ @Override
+ public void clear() {
+ if (fast) {
+ synchronized (this) {
+ map = createMap();
+ }
+ } else {
+ synchronized (map) {
+ map.clear();
+ }
+ }
+ }
+
+ // Basic object methods
+
+
+ /**
+ * Compare the specified object with this list for equality. This
+ * implementation uses exactly the code that is used to define the
+ * list equals function in the documentation for the
+ * {@code Map.equals} method.
+ *
+ * @param o the object to be compared to this list
+ * @return true if the two maps are equal
+ */
+ @Override
+ public boolean equals(final Object o) {
+ // Simple tests that require no synchronization
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof Map)) {
+ return false;
+ }
+ final Map<?, ?> mo = (Map<?, ?>) o;
+
+ // Compare the two maps for equality
+ if (fast) {
+ if (mo.size() != map.size()) {
+ return false;
+ }
+ for (final Map.Entry<K, V> e : map.entrySet()) {
+ final K key = e.getKey();
+ final V value = e.getValue();
+ if (value == null) {
+ if (!(mo.get(key) == null && mo.containsKey(key))) {
+ return false;
+ }
+ } else if (!value.equals(mo.get(key))) {
+ return false;
+ }
+ }
+ return true;
+
+ }
+ synchronized (map) {
+ if (mo.size() != map.size()) {
+ return false;
+ }
+ for (final Map.Entry<K, V> e : map.entrySet()) {
+ final K key = e.getKey();
+ final V value = e.getValue();
+ if (value == null) {
+ if (!(mo.get(key) == null && mo.containsKey(key))) {
+ return false;
+ }
+ } else if (!value.equals(mo.get(key))) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Gets the hash code value for this map. This implementation uses
+ * exactly the code that is used to define the list hash function in the
+ * documentation for the {@code Map.hashCode} method.
+ *
+ * @return suitable integer hash code
+ */
+ @Override
+ public int hashCode() {
+ if (fast) {
+ int h = 0;
+ for (final Map.Entry<K, V> e : map.entrySet()) {
+ h += e.hashCode();
+ }
+ return h;
+ }
+ synchronized (map) {
+ int h = 0;
+ for (final Map.Entry<K, V> e : map.entrySet()) {
+ h += e.hashCode();
+ }
+ return h;
+ }
+ }
+
+ /**
+ * Gets a shallow copy of this {@code FastHashMap} instance.
+ * The keys and values themselves are not copied.
+ *
+ * @return a clone of this map
+ */
+ @Override
+ public Object clone() {
+ WeakFastHashMap<K, V> results = null;
+ if (fast) {
+ results = new WeakFastHashMap<>(map);
+ } else {
+ synchronized (map) {
+ results = new WeakFastHashMap<>(map);
+ }
+ }
+ results.setFast(getFast());
+ return results;
+ }
+
+ // Map views
+
+
+ /**
+ * Gets a collection view of the mappings contained in this map. Each
+ * element in the returned collection is a {@code Map.Entry}.
+ * @return the set of map Map entries
+ */
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
+ return new EntrySet();
+ }
+
+ /**
+ * Gets a set view of the keys contained in this map.
+ * @return the set of the Map's keys
+ */
+ @Override
+ public Set<K> keySet() {
+ return new KeySet();
+ }
+
+ /**
+ * Gets a collection view of the values contained in this map.
+ * @return the set of the Map's values
+ */
+ @Override
+ public Collection<V> values() {
+ return new Values();
+ }
+
+ // Abstractions on Map creations (for subclasses such as WeakFastHashMap)
+
+
+ protected Map<K, V> createMap() {
+ return new WeakHashMap<>();
+ }
+
+ protected Map<K, V> createMap(final int capacity) {
+ return new WeakHashMap<>(capacity);
+ }
+
+ protected Map<K, V> createMap(final int capacity, final float factor) {
+ return new WeakHashMap<>(capacity, factor);
+ }
+
+ protected Map<K, V> createMap(final Map<? extends K, ? extends V> map) {
+ return new WeakHashMap<>(map);
+ }
+
+ protected Map<K, V> cloneMap(final Map<? extends K, ? extends V> map) {
+ return createMap(map);
+ }
+
+ // Map view inner classes
+
+ /**
+ * Abstract collection implementation shared by keySet(), values() and entrySet().
+ *
+ * @param <E> the element type
+ */
+ private abstract class CollectionView<E> implements Collection<E> {
+
+ public CollectionView() {
+ }
+
+ protected abstract Collection<E> get(Map<K, V> map);
+ protected abstract E iteratorNext(Map.Entry<K, V> entry);
+
+ @Override
+ public void clear() {
+ if (fast) {
+ synchronized (WeakFastHashMap.this) {
+ map = createMap();
+ }
+ } else {
+ synchronized (map) {
+ get(map).clear();
+ }
+ }
+ }
+
+ @Override
+ public boolean remove(final Object o) {
+ if (fast) {
+ synchronized (WeakFastHashMap.this) {
+ final Map<K, V> temp = cloneMap(map);
+ final boolean r = get(temp).remove(o);
+ map = temp;
+ return r;
+ }
+ }
+ synchronized (map) {
+ return get(map).remove(o);
+ }
+ }
+
+ @Override
+ public boolean removeAll(final Collection<?> o) {
+ if (fast) {
+ synchronized (WeakFastHashMap.this) {
+ final Map<K, V> temp = cloneMap(map);
+ final boolean r = get(temp).removeAll(o);
+ map = temp;
+ return r;
+ }
+ }
+ synchronized (map) {
+ return get(map).removeAll(o);
+ }
+ }
+
+ @Override
+ public boolean retainAll(final Collection<?> o) {
+ if (fast) {
+ synchronized (WeakFastHashMap.this) {
+ final Map<K, V> temp = cloneMap(map);
+ final boolean r = get(temp).retainAll(o);
+ map = temp;
+ return r;
+ }
+ }
+ synchronized (map) {
+ return get(map).retainAll(o);
+ }
+ }
+
+ @Override
+ public int size() {
+ if (fast) {
+ return get(map).size();
+ }
+ synchronized (map) {
+ return get(map).size();
+ }
+ }
+
+ @Override
+ public boolean isEmpty() {
+ if (fast) {
+ return get(map).isEmpty();
+ }
+ synchronized (map) {
+ return get(map).isEmpty();
+ }
+ }
+
+ @Override
+ public boolean contains(final Object o) {
+ if (fast) {
+ return get(map).contains(o);
+ }
+ synchronized (map) {
+ return get(map).contains(o);
+ }
+ }
+
+ @Override
+ public boolean containsAll(final Collection<?> o) {
+ if (fast) {
+ return get(map).containsAll(o);
+ }
+ synchronized (map) {
+ return get(map).containsAll(o);
+ }
+ }
+
+ @Override
+ public <T> T[] toArray(final T[] o) {
+ if (fast) {
+ return get(map).toArray(o);
+ }
+ synchronized (map) {
+ return get(map).toArray(o);
+ }
+ }
+
+ @Override
+ public Object[] toArray() {
+ if (fast) {
+ return get(map).toArray();
+ }
+ synchronized (map) {
+ return get(map).toArray();
+ }
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (fast) {
+ return get(map).equals(o);
+ }
+ synchronized (map) {
+ return get(map).equals(o);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ if (fast) {
+ return get(map).hashCode();
+ }
+ synchronized (map) {
+ return get(map).hashCode();
+ }
+ }
+
+ @Override
+ public boolean add(final E o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(final Collection<? extends E> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new CollectionViewIterator();
+ }
+
+ private class CollectionViewIterator implements Iterator<E> {
+
+ private Map<K, V> expected;
+ private Map.Entry<K, V> lastReturned;
+ private final Iterator<Map.Entry<K, V>> iterator;
+
+ public CollectionViewIterator() {
+ this.expected = map;
+ this.iterator = expected.entrySet().iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (expected != map) {
+ throw new ConcurrentModificationException();
+ }
+ return iterator.hasNext();
+ }
+
+ @Override
+ public E next() {
+ if (expected != map) {
+ throw new ConcurrentModificationException();
+ }
+ lastReturned = iterator.next();
+ return iteratorNext(lastReturned);
+ }
+
+ @Override
+ public void remove() {
+ if (lastReturned == null) {
+ throw new IllegalStateException();
+ }
+ if (fast) {
+ synchronized (WeakFastHashMap.this) {
+ if (expected != map) {
+ throw new ConcurrentModificationException();
+ }
+ WeakFastHashMap.this.remove(lastReturned.getKey());
+ lastReturned = null;
+ expected = map;
+ }
+ } else {
+ iterator.remove();
+ lastReturned = null;
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets implementation over the keys of the FastHashMap
+ */
+ private class KeySet extends CollectionView<K> implements Set<K> {
+
+ @Override
+ protected Collection<K> get(final Map<K, V> map) {
+ return map.keySet();
+ }
+
+ @Override
+ protected K iteratorNext(final Map.Entry<K, V> entry) {
+ return entry.getKey();
+ }
+
+ }
+
+ /**
+ * Collection implementation over the values of the FastHashMap
+ */
+ private class Values extends CollectionView<V> {
+
+ @Override
+ protected Collection<V> get(final Map<K, V> map) {
+ return map.values();
+ }
+
+ @Override
+ protected V iteratorNext(final Map.Entry<K, V> entry) {
+ return entry.getValue();
+ }
+ }
+
+ /**
+ * Sets implementation over the entries of the FastHashMap
+ */
+ private class EntrySet extends CollectionView<Map.Entry<K, V>> implements Set<Map.Entry<K, V>> {
+
+ @Override
+ protected Collection<Map.Entry<K, V>> get(final Map<K, V> map) {
+ return map.entrySet();
+ }
+
+ @Override
+ protected Map.Entry<K, V> iteratorNext(final Map.Entry<K, V> entry) {
+ return entry;
+ }
+
+ }
+
+}