[] segments = this.segments;
- long sum = 0;
- long check = 0;
- int[] mc = new int[segments.length];
- // Try a few times to get accurate count. On failure due to continuous
- // async changes in table, resort to locking.
- for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
- check = 0;
- sum = 0;
- int mcsum = 0;
- for (int i = 0; i < segments.length; ++i) {
- sum += segments[i].count;
- mcsum += mc[i] = segments[i].modCount;
- }
- if (mcsum != 0) {
- for (int i = 0; i < segments.length; ++i) {
- check += segments[i].count;
- if (mc[i] != segments[i].modCount) {
- check = -1; // force retry
- break;
- }
- }
- }
- if (check == sum) {
- break;
- }
- }
- if (check != sum) { // Resort to locking all segments
- sum = 0;
- for (int i = 0; i < segments.length; ++i) {
- segments[i].lock();
- }
- for (int i = 0; i < segments.length; ++i) {
- sum += segments[i].count;
- }
- for (int i = 0; i < segments.length; ++i) {
- segments[i].unlock();
- }
- }
- if (sum > Integer.MAX_VALUE) {
- return Integer.MAX_VALUE;
- } else {
- return (int) sum;
- }
- }
-
- /**
- * Returns the value to which the specified key is mapped, or {@code null} if this map contains no mapping for the
- * key.
- *
- * More formally, if this map contains a mapping from a key {@code k} to a value {@code v} such that
- * {@code key.equals(k)}, then this method returns {@code v}; otherwise it returns {@code null}. (There can be at
- * most one such mapping.)
- *
- * @throws NullPointerException if the specified key is null
- */
- @Override
- public V get(Object key) {
- int hash = hashOf(key);
- return segmentFor(hash).get(key, hash);
- }
-
- /**
- * Tests if the specified object is a key in this table.
- *
- * @param key possible key
- * @return true if and only if the specified object is a key in this table, as determined by the
- * equals method; false otherwise.
- * @throws NullPointerException if the specified key is null
- */
- @Override
- public boolean containsKey(Object key) {
- int hash = hashOf(key);
- return segmentFor(hash).containsKey(key, hash);
- }
-
- /**
- * Returns true if this map maps one or more keys to the specified value. Note: This method requires a full
- * internal traversal of the hash table, and so is much slower than method containsKey.
- *
- * @param value value whose presence in this map is to be tested
- * @return true if this map maps one or more keys to the specified value
- * @throws NullPointerException if the specified value is null
- */
-
- @Override
- public boolean containsValue(Object value) {
- if (value == null) {
- throw new NullPointerException();
- }
-
- // See explanation of modCount use above
-
- final Segment[] segments = this.segments;
- int[] mc = new int[segments.length];
-
- // Try a few times without locking
- for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
- int mcsum = 0;
- for (int i = 0; i < segments.length; ++i) {
- mcsum += mc[i] = segments[i].modCount;
- if (segments[i].containsValue(value)) {
- return true;
- }
- }
- boolean cleanSweep = true;
- if (mcsum != 0) {
- for (int i = 0; i < segments.length; ++i) {
- if (mc[i] != segments[i].modCount) {
- cleanSweep = false;
- break;
- }
- }
- }
- if (cleanSweep) {
- return false;
- }
- }
- // Resort to locking all segments
- for (int i = 0; i < segments.length; ++i) {
- segments[i].lock();
- }
- boolean found = false;
- try {
- for (int i = 0; i < segments.length; ++i) {
- if (segments[i].containsValue(value)) {
- found = true;
- break;
- }
- }
- } finally {
- for (int i = 0; i < segments.length; ++i) {
- segments[i].unlock();
- }
- }
- return found;
- }
-
- public boolean contains(Object value) {
- return containsValue(value);
- }
-
- /**
- * Maps the specified key to the specified value in this table. Neither the key nor the value can be null.
- *
- * The value can be retrieved by calling the get method with a key that is equal to the original key.
- *
- * @param key key with which the specified value is to be associated
- * @param value value to be associated with the specified key
- * @return the previous value associated with key, or null if there was no mapping for
- * key
- * @throws NullPointerException if the specified key or value is null
- */
- @Override
- public V put(K key, V value) {
- if (value == null) {
- throw new NullPointerException();
- }
- int hash = hashOf(key);
- return segmentFor(hash).put(key, hash, value, false);
- }
-
- /**
- * {@inheritDoc}
- *
- * @return the previous value associated with the specified key, or null if there was no mapping for the
- * key
- * @throws NullPointerException if the specified key or value is null
- */
- public V putIfAbsent(K key, V value) {
- if (value == null) {
- throw new NullPointerException();
- }
- int hash = hashOf(key);
- return segmentFor(hash).put(key, hash, value, true);
- }
-
- /**
- * Removes the key (and its corresponding value) from this map. This method does nothing if the key is not in the
- * map.
- *
- * @param key the key that needs to be removed
- * @return the previous value associated with key, or null if there was no mapping for
- * key
- * @throws NullPointerException if the specified key is null
- */
- @Override
- public V remove(Object key) {
- int hash = hashOf(key);
- return segmentFor(hash).remove(key, hash, null, false);
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws NullPointerException if the specified key is null
- */
- public boolean remove(Object key, Object value) {
- int hash = hashOf(key);
- if (value == null) {
- return false;
- }
- return segmentFor(hash).remove(key, hash, value, false) != null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws NullPointerException if any of the arguments are null
- */
- public boolean replace(K key, V oldValue, V newValue) {
- if (oldValue == null || newValue == null) {
- throw new NullPointerException();
- }
- int hash = hashOf(key);
- return segmentFor(hash).replace(key, hash, oldValue, newValue);
- }
-
- /**
- * {@inheritDoc}
- *
- * @return the previous value associated with the specified key, or null if there was no mapping for the
- * key
- * @throws NullPointerException if the specified key or value is null
- */
- public V replace(K key, V value) {
- if (value == null) {
- throw new NullPointerException();
- }
- int hash = hashOf(key);
- return segmentFor(hash).replace(key, hash, value);
- }
-
- /**
- * Removes all of the mappings from this map.
- */
- @Override
- public void clear() {
- for (int i = 0; i < segments.length; ++i) {
- segments[i].clear();
- }
- }
-
- @Override
- public Set keySet() {
- Set ks = keySet;
- return ks != null ? ks : (keySet = new KeySet());
- }
-
- @Override
- public Collection values() {
- Collection vs = values;
- return vs != null ? vs : (values = new Values());
- }
-
- @Override
- public Set> entrySet() {
- Set> es = entrySet;
- return es != null ? es : (entrySet = new EntrySet());
- }
-
- /**
- * Returns an enumeration of the keys in this table.
- *
- * @return an enumeration of the keys in this table
- * @see #keySet()
- */
- public Enumeration keys() {
- return new KeyIterator();
- }
-
- /**
- * Returns an enumeration of the values in this table.
- *
- * @return an enumeration of the values in this table
- * @see #values()
- */
- public Enumeration elements() {
- return new ValueIterator();
- }
-
- /* ---------------- Iterator Support -------------- */
-
- abstract class HashIterator {
-
- int nextSegmentIndex;
- int nextTableIndex;
- HashEntry[] currentTable;
- HashEntry nextEntry;
- HashEntry lastReturned;
- K currentKey; // Strong reference to weak key (prevents gc)
-
- HashIterator(){
- nextSegmentIndex = segments.length - 1;
- nextTableIndex = -1;
- advance();
- }
-
- public boolean hasMoreElements() {
- return hasNext();
- }
-
- final void advance() {
- if (nextEntry != null && (nextEntry = nextEntry.next) != null) {
- return;
- }
-
- while (nextTableIndex >= 0) {
- if ((nextEntry = currentTable[nextTableIndex--]) != null) {
- return;
- }
- }
-
- while (nextSegmentIndex >= 0) {
- Segment seg = segments[nextSegmentIndex--];
- if (seg.count != 0) {
- currentTable = seg.table;
- for (int j = currentTable.length - 1; j >= 0; --j) {
- if ((nextEntry = currentTable[j]) != null) {
- nextTableIndex = j - 1;
- return;
- }
- }
- }
- }
- }
-
- public boolean hasNext() {
- while (nextEntry != null) {
- if (nextEntry.key() != null) {
- return true;
- }
- advance();
- }
-
- return false;
- }
-
- HashEntry nextEntry() {
- do {
- if (nextEntry == null) {
- throw new NoSuchElementException();
- }
-
- lastReturned = nextEntry;
- currentKey = lastReturned.key();
- advance();
- } while (currentKey == null); // Skip GC'd keys
-
- return lastReturned;
- }
-
- public void remove() {
- if (lastReturned == null) {
- throw new IllegalStateException();
- }
- ConcurrentIdentityHashMap.this.remove(currentKey);
- lastReturned = null;
- }
- }
-
- final class KeyIterator extends HashIterator implements Iterator, Enumeration {
-
- public K next() {
- return super.nextEntry().key();
- }
-
- public K nextElement() {
- return super.nextEntry().key();
- }
- }
-
- final class ValueIterator extends HashIterator implements Iterator, Enumeration {
-
- public V next() {
- return super.nextEntry().value();
- }
-
- public V nextElement() {
- return super.nextEntry().value();
- }
- }
-
- /*
- * This class is needed for JDK5 compatibility.
- */
- static class SimpleEntry implements Entry {
-
- private final K key;
-
- private V value;
-
- public SimpleEntry(K key, V value){
- this.key = key;
- this.value = value;
-
- }
-
- public SimpleEntry(Entry extends K, ? extends V> entry){
- this.key = entry.getKey();
- this.value = entry.getValue();
-
- }
-
- public K getKey() {
- return key;
- }
-
- public V getValue() {
- return value;
- }
-
- public V setValue(V value) {
- V oldValue = this.value;
- this.value = value;
- return oldValue;
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof Map.Entry, ?>)) {
- return false;
- }
- @SuppressWarnings("unchecked")
- Map.Entry e = (Map.Entry) o;
- return eq(key, e.getKey()) && eq(value, e.getValue());
- }
-
- @Override
- public int hashCode() {
- return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode());
- }
-
- @Override
- public String toString() {
- return key + "=" + value;
- }
-
- private static boolean eq(Object o1, Object o2) {
- return o1 == null ? o2 == null : o1.equals(o2);
- }
- }
-
- /**
- * Custom Entry class used by EntryIterator.next(), that relays setValue changes to the underlying map.
- */
- final class WriteThroughEntry extends SimpleEntry {
-
- WriteThroughEntry(K k, V v){
- super(k, v);
- }
-
- /**
- * Set our entry's value and write through to the map. The value to return is somewhat arbitrary here. Since a
- * WriteThroughEntry does not necessarily track asynchronous changes, the most recent "previous" value could be
- * different from what we return (or could even have been removed in which case the put will re-establish). We
- * do not and can not guarantee more.
- */
- @Override
- public V setValue(V value) {
-
- if (value == null) {
- throw new NullPointerException();
- }
- V v = super.setValue(value);
- ConcurrentIdentityHashMap.this.put(getKey(), value);
- return v;
- }
-
- }
-
- final class EntryIterator extends HashIterator implements Iterator> {
-
- public Map.Entry next() {
- HashEntry e = super.nextEntry();
- return new WriteThroughEntry(e.key(), e.value());
- }
- }
-
- final class KeySet extends AbstractSet {
-
- @Override
- public Iterator iterator() {
-
- return new KeyIterator();
- }
-
- @Override
- public int size() {
- return ConcurrentIdentityHashMap.this.size();
- }
-
- @Override
- public boolean isEmpty() {
- return ConcurrentIdentityHashMap.this.isEmpty();
- }
-
- @Override
- public boolean contains(Object o) {
- return ConcurrentIdentityHashMap.this.containsKey(o);
- }
-
- @Override
- public boolean remove(Object o) {
- return ConcurrentIdentityHashMap.this.remove(o) != null;
-
- }
-
- @Override
- public void clear() {
- ConcurrentIdentityHashMap.this.clear();
- }
- }
-
- final class Values extends AbstractCollection {
-
- @Override
- public Iterator iterator() {
- return new ValueIterator();
- }
-
- @Override
- public int size() {
- return ConcurrentIdentityHashMap.this.size();
- }
-
- @Override
- public boolean isEmpty() {
- return ConcurrentIdentityHashMap.this.isEmpty();
- }
-
- @Override
- public boolean contains(Object o) {
- return ConcurrentIdentityHashMap.this.containsValue(o);
- }
-
- @Override
- public void clear() {
- ConcurrentIdentityHashMap.this.clear();
- }
- }
-
- final class EntrySet extends AbstractSet> {
-
- @Override
- public Iterator> iterator() {
- return new EntryIterator();
- }
-
- @Override
- public boolean contains(Object o) {
- if (!(o instanceof Map.Entry, ?>)) {
- return false;
- }
- Map.Entry, ?> e = (Map.Entry, ?>) o;
- V v = ConcurrentIdentityHashMap.this.get(e.getKey());
- return v != null && v.equals(e.getValue());
- }
-
- @Override
- public boolean remove(Object o) {
- if (!(o instanceof Map.Entry, ?>)) {
- return false;
- }
- Map.Entry, ?> e = (Map.Entry, ?>) o;
- return ConcurrentIdentityHashMap.this.remove(e.getKey(), e.getValue());
- }
-
- @Override
- public int size() {
- return ConcurrentIdentityHashMap.this.size();
- }
-
- @Override
- public boolean isEmpty() {
- return ConcurrentIdentityHashMap.this.isEmpty();
- }
-
- @Override
- public void clear() {
- ConcurrentIdentityHashMap.this.clear();
- }
- }
-}
diff --git a/src/test/java/com/alibaba/druid/bvt/utils/ConcurrentIdentityHashMapTest.java b/src/test/java/com/alibaba/druid/bvt/utils/ConcurrentIdentityHashMapTest.java
deleted file mode 100644
index 9b26d9e364..0000000000
--- a/src/test/java/com/alibaba/druid/bvt/utils/ConcurrentIdentityHashMapTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.alibaba.druid.bvt.utils;
-
-import junit.framework.TestCase;
-
-import org.junit.Assert;
-
-import com.alibaba.druid.util.ConcurrentIdentityHashMap;
-
-public class ConcurrentIdentityHashMapTest extends TestCase {
-
- public void test_0() throws Exception {
- ConcurrentIdentityHashMap map = new ConcurrentIdentityHashMap();
-
- Integer v1 = new Integer(3);
- map.put(v1, "3");
-
- Assert.assertTrue(map.contains("3"));
- Assert.assertTrue(map.containsKey(v1));
-
- Assert.assertFalse(map.contains("4"));
- Assert.assertFalse(map.containsKey(new Integer(3)));
-
- map.put(v1, "33");
- Assert.assertFalse(map.contains("3"));
- Assert.assertTrue(map.contains("33"));
-
- Assert.assertEquals(1, map.size());
-
- map.clear();
- Assert.assertEquals(0, map.size());
- }
-}
diff --git a/src/test/java/com/alibaba/druid/bvt/utils/ConcurrentIdentityHashMapTest2.java b/src/test/java/com/alibaba/druid/bvt/utils/ConcurrentIdentityHashMapTest2.java
deleted file mode 100644
index d841978f5b..0000000000
--- a/src/test/java/com/alibaba/druid/bvt/utils/ConcurrentIdentityHashMapTest2.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.alibaba.druid.bvt.utils;
-
-import junit.framework.TestCase;
-
-import org.junit.Assert;
-
-import com.alibaba.druid.util.ConcurrentIdentityHashMap;
-
-public class ConcurrentIdentityHashMapTest2 extends TestCase {
-
- public void test_0() throws Exception {
- ConcurrentIdentityHashMap map = new ConcurrentIdentityHashMap();
- map.put(Integer.valueOf(1), "");
- Assert.assertEquals(map.get(Integer.valueOf(1)), "");
- Assert.assertEquals(map.get(new Integer(1)), null);
-
- Assert.assertTrue(map.containsValue(""));
-
- {
- Exception error = null;
- try {
- map.containsValue(null);
- } catch (NullPointerException ex) {
- error = ex;
- }
- Assert.assertNotNull(error);
- }
- {
- Exception error = null;
- try {
- map.put(Integer.valueOf(1), null);
- } catch (NullPointerException ex) {
- error = ex;
- }
- Assert.assertNotNull(error);
- }
- {
- Exception error = null;
- try {
- map.putIfAbsent(Integer.valueOf(1), null);
- } catch (NullPointerException ex) {
- error = ex;
- }
- Assert.assertNotNull(error);
- }
-
- map.put(Integer.valueOf(1), "123");
- Assert.assertEquals(map.get(Integer.valueOf(1)), "123");
- Assert.assertEquals(map.get(new Integer(1)), null);
-
- map.putIfAbsent(Integer.valueOf(1), "234");
- Assert.assertEquals(map.get(Integer.valueOf(1)), "123");
- Assert.assertEquals(map.get(new Integer(1)), null);
-
- map.remove(new Integer(1));
- Assert.assertEquals(map.get(Integer.valueOf(1)), "123");
- Assert.assertFalse(map.isEmpty());
-
- map.remove(Integer.valueOf(1));
- Assert.assertEquals(map.get(Integer.valueOf(1)), null);
- Assert.assertTrue(map.isEmpty());
- }
-}
diff --git a/src/test/java/com/alibaba/druid/bvt/utils/ConcurrentIdentityHashMapTest3.java b/src/test/java/com/alibaba/druid/bvt/utils/ConcurrentIdentityHashMapTest3.java
deleted file mode 100644
index 356aecd56c..0000000000
--- a/src/test/java/com/alibaba/druid/bvt/utils/ConcurrentIdentityHashMapTest3.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.alibaba.druid.bvt.utils;
-
-import java.util.Map;
-
-import junit.framework.TestCase;
-
-import org.junit.Assert;
-
-import com.alibaba.druid.util.ConcurrentIdentityHashMap;
-
-public class ConcurrentIdentityHashMapTest3 extends TestCase {
-
- public void test_0() throws Exception {
- ConcurrentIdentityHashMap map = new ConcurrentIdentityHashMap(16, 0.75f, 2);
-
- Integer[] keys = new Integer[10000];
- for (int i = 0; i < keys.length; ++i) {
- keys[i] = i;
- }
- for (int i = 0; i < keys.length; ++i) {
- map.put(keys[i], "");
- }
- Assert.assertEquals(keys.length, map.size());
- for (int i = 0; i < keys.length; ++i) {
- map.put(keys[i], "");
- }
- for (Map.Entry entry : map.entrySet()) {
- entry.getKey();
- entry.getValue();
- }
- Assert.assertEquals(keys.length, map.size());
-
- for (int i = 0; i < keys.length; ++i) {
- map.replace(keys[i], "", "a");
- }
- for (int i = 0; i < keys.length; ++i) {
- map.replace(keys[i], "", "b");
- }
- for (int i = 0; i < keys.length; ++i) {
- map.replace(keys[i], "");
- }
- Assert.assertEquals(keys.length, map.size());
-
- map.keys();
- map.keys().hasMoreElements();
- map.keys().nextElement();
-
- for (int i = 0; i < keys.length; ++i) {
- map.remove(keys[i]);
- }
- Assert.assertEquals(0, map.size());
-
- map.keys();
- map.entrySet();
- map.size();
- map.clear();
- map.isEmpty();
-
- map.entrySet().size();
- map.entrySet().isEmpty();
- map.entrySet().remove(null);
- map.entrySet().clear();
- map.entrySet().contains("");
-
- map.values().size();
- map.values().isEmpty();
- map.values().remove(null);
- map.values().clear();
- map.values().contains("");
-
- map.keySet().size();
- map.keySet().isEmpty();
- map.keySet().remove(null);
- map.keySet().clear();
- map.keySet().contains("");
-
- }
-}