Ranides Atterwim 11 yıl önce
ebeveyn
işleme
8ef0028424

+ 318 - 468
assira/src/main/java/net/ranides/assira/collection/lookups/AHashLookup.java

@@ -17,16 +17,13 @@ import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
 import net.ranides.assira.collection.utils.HashCollection;
+import net.ranides.assira.generic.ValueUtils;
 import net.ranides.assira.math.MathUtils;
 
 /**
  * A type-specific hash map with primitive int values.
- * @todo (assira # 2) review.hash.map V=int
+ * @todo (assira # 8) review.hash.map V=int
  */
-@SuppressWarnings({
-    "PMD.AvoidReassigningParameters",
-    "EqualsAndHashcode"
-})
 public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serializable {
 
     private static final long serialVersionUID = 4L;
@@ -54,7 +51,7 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
      * Threshold after which we rehash. It must be the table size times
      * {@link #factor}.
      */
-    protected transient int maxFill;
+    protected transient int capacity;
     /**
      * The mask for wrapping a position counter.
      */
@@ -98,192 +95,52 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
         this.factor = f;
         n = HashCollection.arraysize(expected, f);
         mask = n - 1;
-        maxFill = HashCollection.factorsize(n, f);
+        capacity = HashCollection.factorsize(n, f);
         keys = (K[]) new Object[n];
         values = new int[n];
         used = new boolean[n];
     }
     
-    protected abstract int hashkey(K key);
+    protected abstract int hash(K key);
     
-    protected abstract boolean cmpkey(K key1, K key2);
+    protected abstract boolean compare(K key1, K key2);
 
     @Override
     public final int put(K key, int value) {
-        // The starting point.
-        int pos = HashUtils.murmurHash3(hashkey(key)) & mask;
-        // There's always an unused entry.
-        while (used[ pos]) {
-            if (cmpkey(keys[pos], key)) {
-                int oldValue = values[pos];
-                values[ pos] = value;
-                return oldValue;
-            }
-            pos = (pos + 1) & mask;
-        }
-        used[ pos] = true;
-        keys[ pos] = key;
-        values[ pos] = value;
-        if (++size >= maxFill) {
-            rehash(HashCollection.arraysize(size + 1, factor));
-        }
-        return defRetValue;
+		int pos = ifind(key);
+        return used[pos] ? ireplace(pos, value) : iinsert(pos, key, value);
     }
 
     @Override
     public final Integer put(K key, Integer value) {
-        int v = value;
-        // The starting point.
-        int pos = HashUtils.murmurHash3(hashkey(key)) & mask;
-        // There's always an unused entry.
-        while (used[ pos]) {
-            if (cmpkey(keys[ pos], key)) {
-                Integer oldValue = values[pos];
-                values[pos] = v;
-                return oldValue;
-            }
-            pos = (pos + 1) & mask;
-        }
-        used[ pos] = true;
-        keys[ pos] = key;
-        values[ pos] = v;
-        if (++size >= maxFill) {
-            rehash(HashCollection.arraysize(size + 1, factor));
-        }
-        return null;
-    }
-
-    /**
-     * Adds an increment to values currently associated with a keys.
-     *
-     * <P>Note that this method respects the
-     * {@link #defaultReturnValue() default return values} semantics: when
- called with a keys that does not currently appears in the map, the keys
- will be associated with the default return values plus the given
- increment.
-     *
-     * @param key the keys.
-     * @param delta the increment.
-     * @return the old values, or the
-    {@link #defaultReturnValue() default return values} if no values was
- present for the given keys.
-     */
-    public final int addTo(K key, int delta) {
-        // The starting point.
-        int pos = HashUtils.murmurHash3(hashkey((K)key)) & mask;
-        // There's always an unused entry.
-        while (used[ pos]) {
-            if (cmpkey(keys[ pos], key)) {
-                int oldValue = values[ pos];
-                values[ pos] += delta;
-                return oldValue;
-            }
-            pos = (pos + 1) & mask;
-        }
-        used[ pos] = true;
-        keys[ pos] = key;
-        values[ pos] = defRetValue + delta;
-        if (++size >= maxFill) {
-            rehash(HashCollection.arraysize(size + 1, factor));
-        }
-        return defRetValue;
-    }
-
-    /**
-     * Shifts left mentries with the specified hash code, starting at the
- specified position, and empties the resulting free entry.
-     *
-     * @param pos a starting position.
-     * @return the position cleared by the shifting process.
-     */
-    private final int shiftKeys(int pos) {
-        // Shift mentries with the same hash.
-        int last, slot;
-        for (;;) {
-            pos = ((last = pos) + 1) & mask;
-            while (used[ pos]) {
-                slot = HashUtils.murmurHash3(hashkey((K)keys[ pos])) & mask;
-                if (last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos) {
-                    break;
-                }
-                pos = (pos + 1) & mask;
-            }
-            if (!used[ pos]) {
-                break;
-            }
-            keys[ last] = keys[ pos];
-            values[ last] = values[ pos];
-        }
-        used[ last] = false;
-        keys[ last] = null;
-        return last;
+		return put(key, value.intValue());
     }
 
     @SuppressWarnings("unchecked")
     @Override
     public final int removeInt(Object key) {
-        // The starting point.
-        int pos = HashUtils.murmurHash3(hashkey((K)key)) & mask;
-        // There's always an unused entry.
-        while (used[ pos]) {
-            if (cmpkey(keys[ pos], (K)key)) {
-                size--;
-                int v = values[ pos];
-                shiftKeys(pos);
-                return v;
-            }
-            pos = (pos + 1) & mask;
-        }
-        return defRetValue;
+		int pos = ifind((K)key);
+        return used[pos] ? ishift(pos) : defRetValue;
     }
 
     @SuppressWarnings("unchecked")
     @Override
     public final Integer remove(Object key) {
-        K kkey = (K)key;
-        // The starting point.
-        int pos = HashUtils.murmurHash3(hashkey((K)kkey)) & mask;
-        // There's always an unused entry.
-        while (used[ pos]) {
-            if (cmpkey(keys[pos], kkey)) {
-                size--;
-                int v = values[ pos];
-                shiftKeys(pos);
-                return v;
-            }
-            pos = (pos + 1) & mask;
-        }
-        return null;
+        int pos = ifind((K)key);
+        return used[pos] ? ishift(pos) : defRetValue;
     }
 
     @SuppressWarnings("unchecked")
     @Override
     public final int getInt(Object key) {
-        // The starting point.
-        int pos = HashUtils.murmurHash3(hashkey((K)key)) & mask;
-        // There's always an unused entry.
-        while (used[ pos]) {
-            if (cmpkey(keys[pos], (K)key)) {
-                return values[pos];
-            }
-            pos = (pos + 1) & mask;
-        }
-        return defRetValue;
+        int pos = ifind((K)key);
+        return used[pos] ? values[pos] : defRetValue; 
     }
 
     @SuppressWarnings("unchecked")
     @Override
     public boolean containsKey(Object key) {
-        // The starting point.
-        int pos = HashUtils.murmurHash3(hashkey((K)key)) & mask;
-        // There's always an unused entry.
-        while (used[ pos]) {
-            if (cmpkey(keys[pos], (K)key)) {
-                return true;
-            }
-            pos = (pos + 1) & mask;
-        }
-        return false;
+        return used[ifind((K)key)];
     }
 
     @Override
@@ -297,12 +154,6 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
         }
         return false;
     }
-    /* Removes all elements from this map.
-     *
-     * <P>To increase object reuse, this method does not change the table size.
-     * If you want to reduce the table size, you must use {@link #trim()}.
-     *
-     */
 
     @Override
     public final void clear() {
@@ -311,7 +162,6 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
         }
         size = 0;
         ArrayUtils.fill(used, false);
-        // We null all object mentries so that the garbage collector can do its work.
         ArrayUtils.fill(keys, null);
     }
 
@@ -324,13 +174,287 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
     public final boolean isEmpty() {
         return size == 0;
     }
+	
+	@Override
+    public final Set<LookupEntry<K>> fastEntrySet() {
+        if (mentries == null) {
+            mentries = new MapEntrySet();
+        }
+        return mentries;
+    }
+	
+	@Override
+    public final Set<K> keySet() {
+        if (mkeys == null) {
+            mkeys = new KeySet();
+        }
+        return mkeys;
+    }
+	
+	@Override
+    public final IntCollection values() {
+        if (mvalues == null) {
+            mvalues = new IntCollection() {
+                @Override
+                public IntIterator iterator() {
+                    return new ValueIterator();
+                }
+
+                @Override
+                public int size() {
+                    return size;
+                }
+
+                @Override
+                public boolean contains(int v) {
+                    return containsValue(v);
+                }
+
+                @Override
+                public void clear() {
+                    AHashLookup.this.clear();
+                }
+            };
+        }
+        return mvalues;
+    }
+
+    /**
+     * Rehashes the map, making the table as small as possible.
+     *
+     * <P>This method rehashes the table to the smallest size satisfying the
+     * load factor. It can be used when the set will not be changed anymore, so
+     * to optimize access speed and size.
+     *
+     * <P>If the table size is already the minimum possible, this method does
+     * nothing.
+     *
+     * @return true if there was enough memory to trim the map.
+     * @see #trim(int)
+     */
+    public final boolean trim() {
+        int l = HashCollection.arraysize(size, factor);
+        if (l >= n) {
+            return true;
+        }
+        try {
+            irehash(l);
+        } catch (OutOfMemoryError cantDoIt) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Rehashes this map if the table is too large.
+     *
+     * <P>Let <var>N</var> be the smallest table size that can hold
+     * <code>max(n,{@link #size()})</code> mentries, still satisfying the load
+     * factor. If the current table size is smaller than or equal to
+     * <var>N</var>, this method does nothing. Otherwise, it rehashes this map
+     * in a table of size
+     * <var>N</var>.
+     *
+     * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
+	 * map} leaves the table size untouched. If you are reusing a map many
+     * times, you can call this method with a typical size to avoid keeping
+     * around a very large table just because of a few large transient maps.
+     *
+     * @param n the threshold for the trimming.
+     * @return true if there was enough memory to trim the map.
+     * @see #trim()
+     */
+    public final boolean trim(int n) {
+        int l = MathUtils.pow2next((int) Math.ceil(n / factor));
+        if (this.n <= l) {
+            return true;
+        }
+        try {
+            irehash(l);
+        } catch (OutOfMemoryError cantDoIt) {
+            return false;
+        }
+        return true;
+    }
 
     /**
-     * The entry class for a hash map does not record keys and values, but rather
- the position in the hash table of the corresponding entry. This is
-     * necessary so that calls to {@link java.util.Map.Entry#setValue(Object)}
-     * are reflected in the map
+     * Returns a hash code for this map.
+     *
+     * This method overrides the generic method provided by the superclass.
+     * Since
+     * <code>equals()</code> is not overriden, it is important that the values
+     * returned by this method is the same values as the one returned by the
+     * overriden method.
+     *
+     * @return a hash code for this map.
      */
+    @Override
+    public final int hashCode() {
+        int h = 0;
+        for (int j = size, i = 0, t = 0; j-- != 0;) {
+            while (!used[ i]) {
+                i++;
+            }
+            if (this != keys[ i]) {
+                t = hash((K)keys[i]);
+            }
+            t ^= values[i];
+            h += t;
+            i++;
+        }
+        return h;
+    }
+
+    @Override
+    public final boolean equals(Object object) {
+        return super.equals(object);
+    }
+	
+
+    /**
+     * Resizes the map.
+     *
+     * <P>This method implements the basic rehashing strategy, and may be
+     * overriden by subclasses implementing different rehashing strategies
+     * (e.g., disk-based rehashing). However, you should not override this
+     * method unless you understand the internal workings of this class.
+     *
+     * @param newN the new size
+     */
+    @SuppressWarnings("unchecked")
+    protected final void irehash(int newN) {
+        int i = 0, pos;
+        boolean nused[] = this.used;
+        K ckey;
+        K ikeys[] = this.keys;
+        int ivalues[] = this.values;
+        int newMask = newN - 1;
+        K newKey[] = (K[]) new Object[newN];
+        int newValue[] = new int[newN];
+        boolean newUsed[] = new boolean[newN];
+        for (int j = size; j-- != 0;) {
+            while (!nused[ i]) {
+                i++;
+            }
+            ckey = ikeys[ i];
+            pos = HashUtils.murmurHash3(hash((K)ckey)) & newMask;
+            while (newUsed[ pos]) {
+                pos = (pos + 1) & newMask;
+            }
+            newUsed[ pos] = true;
+            newKey[ pos] = ckey;
+            newValue[ pos] = ivalues[ i];
+            i++;
+        }
+        n = newN;
+        mask = newMask;
+        capacity = HashCollection.factorsize(n, factor);
+        this.keys = newKey;
+        this.values = newValue;
+        this.used = newUsed;
+    }
+	
+	protected int ifind(K key) {
+        // There's always an unused entry.
+        int i = HashUtils.murmurHash3(hash((K)key)) & mask;
+        while (used[i] && !compare(keys[i], key)) {
+            i = (i+1) & mask;
+        }
+        return i;
+    }
+    
+    protected int ireplace(int segment, int value) {
+        int prev = values[segment];
+        values[segment] = value;
+        return prev;
+    }
+    
+    protected int iinsert(int segment, K key, int value) {
+        used[segment] = true;
+        keys[segment] = key;
+        values[segment] = value;
+        
+        if (++size >= capacity) {
+            irehash(HashCollection.arraysize(size + 1, factor));
+        }
+        return defRetValue;
+    }
+
+    protected final int ishift(int pos) {
+        size--;
+        int prev = values[pos];
+        int last;
+        for (;;) {
+            last = pos;
+            pos = inext(pos);
+            if (!used[pos]) {
+                break;
+            }
+            imove(last, pos);
+        }
+        iclear(last);
+        return prev;
+    }
+        
+    protected int inext(int last) {
+        int pos = (last+1) & mask;
+        while (used[pos]) {
+            int slot = HashUtils.murmurHash3(hash((K)keys[pos])) & mask;
+            if (last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos) {
+                break;
+            }
+            pos = (pos + 1) & mask;
+        }
+        return pos;
+    }
+    
+    protected void imove(int target, int source) {
+        keys[target] = keys[source];
+        values[target] = values[source];
+    }
+    
+    protected void iclear(int segment) {
+        used[segment] = false;
+        keys[segment] = null;
+    }
+
+    private void writeObject(java.io.ObjectOutputStream ostream) throws java.io.IOException {
+        K ikeys[] = this.keys;
+        int ivalues[] = this.values;
+        MapIterator iterator = new MapIterator();
+        ostream.defaultWriteObject();
+        for (int j = size, element; j-- != 0;) {
+            element = iterator.nextEntry();
+            ostream.writeObject(ikeys[ element]);
+            ostream.writeInt(ivalues[ element]);
+        }
+    }
+
+    @SuppressWarnings({
+        "unchecked",
+        "MismatchedReadAndWriteOfArray"
+    })
+    private void readObject(java.io.ObjectInputStream istream) throws java.io.IOException, ClassNotFoundException {
+        istream.defaultReadObject();
+        n = HashCollection.arraysize(size, factor);
+        capacity = HashCollection.factorsize(n, factor);
+        mask = n - 1;
+        K ikeys[] = this.keys = (K[]) new Object[n];
+        int ivalues[] = this.values = new int[n];
+        boolean iused[] = this.used = new boolean[n];
+        for (int i = size, pos; i-- != 0;) {
+            K ckey = (K) istream.readObject();
+            int cval = istream.readInt();
+            pos = HashUtils.murmurHash3(hash((K)ckey)) & mask;
+            while (iused[ pos]) {
+                pos = (pos + 1) & mask;
+            }
+            iused[pos] = true;
+            ikeys[pos] = ckey;
+            ivalues[pos] = cval;
+        }
+    }
+
     private final class MapEntry implements LookupEntry<K>, Map.Entry<K, Integer> {
         // The table index this entry refers to, or -1 if this entry has been deleted.
 
@@ -376,17 +500,17 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
             Map.Entry<K, Integer> entry = (Map.Entry<K, Integer>) object;
             K key = entry.getKey();
             int v = entry.getValue();
-            return cmpkey(keys[index], key) && (values[index] == v);
+            return compare(keys[index], key) && (values[index] == v);
         }
 
         @Override
         public int hashCode() {
-            return (hashkey((K)keys[ index])) ^ (values[ index]);
+            return (hash((K)keys[index])) ^ (values[index]);
         }
 
         @Override
         public String toString() {
-            return keys[ index] + "=>" + values[ index];
+            return keys[index] + "=>" + values[index];
         }
     }
 
@@ -413,9 +537,9 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
         int counter;
         /**
          * A lazily allocated list containing the mkeys of elements that have
- wrapped around the table because of removals; such elements would not
- be enumerated (other elements would be usually enumerated twice in
- their place).
+         * wrapped around the table because of removals; such elements would not
+         * be enumerated (other elements would be usually enumerated twice in
+         * their place).
          */
         ArrayList<K> wrapped;
        
@@ -443,14 +567,9 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
             // We are just enumerating elements from the wrapped list.
             if (pos < 0) {
                 K ckey = wrapped.get(-(last = --pos) - 2);
-                // The starting point.
-                int cpos = HashUtils.murmurHash3(hashkey(ckey)) & mask;
-                // There's always an unused entry.
-                while (used[ cpos]) {
-                    if (cmpkey(keys[ cpos], ckey)) {
-                        return cpos;
-                    }
-                    cpos = (cpos + 1) & mask;
+				int pos = ifind(ckey);
+                if(used[pos]) {
+                    return pos;
                 }
             }
             last = pos;
@@ -463,43 +582,24 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
             return last;
         }
 
-        /**
-         * Shifts left mentries with the specified hash code, starting at the
- specified position, and empties the resulting free entry. If any
-         * entry wraps around the table, instantiates lazily {@link #wrapped}
- and stores the entry keys.
-         *
-         * @param pos a starting position.
-         * @return the position cleared by the shifting process.
-         */
-        protected final int shiftKeys(int pos) {
-            // Shift mentries with the same hash.
-            int ilast, islot;
+        protected final int ishift(int pos) {
+            int last;
             for (;;) {
-                pos = ((ilast = pos) + 1) & mask;
-                while (used[ pos]) {
-                    islot = HashUtils.murmurHash3(hashkey((K)keys[ pos])) & mask;
-                    if (ilast <= pos ? ilast >= islot || islot > pos : ilast >= islot && islot > pos) {
-                        break;
-                    }
-                    pos = (pos + 1) & mask;
-                }
+                last = pos;
+                pos = inext(last);
                 if (!used[ pos]) {
                     break;
                 }
-                if (pos < ilast) {
-                    // Wrapped entry.
+                if (pos < last) {
                     if (wrapped == null) {
                         wrapped = new ArrayList<>();
                     }
-                    wrapped.add(keys[ pos]);
+                    wrapped.add(keys[pos]);
                 }
-                keys[ ilast] = keys[ pos];
-                values[ ilast] = values[ pos];
+                imove(last, pos);
             }
-            used[ ilast] = false;
-            keys[ ilast] = null;
-            return ilast;
+            iclear(last);
+            return last;
         }
 
         @SuppressWarnings("unchecked")
@@ -514,7 +614,7 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
                 return;
             }
             size--;
-            if (shiftKeys(last) == pos && counter > 0) {
+            if (ishift(last) == pos && counter > 0) {
                 counter++;
                 nextEntry();
             }
@@ -581,18 +681,8 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
                 return false;
             }
             Map.Entry<K, Integer> entry = (Map.Entry<K, Integer>) object;
-            K ckey = entry.getKey();
-            // The starting point.
-            int pos = HashUtils.murmurHash3(hashkey((K)ckey)) & mask;
-            // There's always an unused entry.
-            while (used[ pos]) {
-                if (cmpkey(keys[ pos], ckey)) {
-                    int v = entry.getValue();
-                    return values[pos] == v;
-                }
-                pos = (pos + 1) & mask;
-            }
-            return false;
+			int pos = ifind(entry.getKey());
+			return used[pos] && ValueUtils.equals(entry.getValue(), values[pos]);
         }
 
         @SuppressWarnings("unchecked")
@@ -602,18 +692,9 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
                 return false;
             }
             Map.Entry<K, Integer> entry = (Map.Entry<K, Integer>) object;
-            K ckey = entry.getKey();
-            // The starting point.
-            int pos = HashUtils.murmurHash3(hashkey((K)ckey)) & mask;
-            // There's always an unused entry.
-            while (used[ pos]) {
-                if (cmpkey(keys[pos], (K)ckey)) {
-                    AHashLookup.this.remove(entry.getKey());
-                    return true;
-                }
-                pos = (pos + 1) & mask;
-            }
-            return false;
+            int prev = size;
+            AHashLookup.this.remove(entry.getKey());
+            return size != prev;
         }
 
         @Override
@@ -627,22 +708,6 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
         }
     }
 
-    @Override
-    public final Set<LookupEntry<K>> fastEntrySet() {
-        if (mentries == null) {
-            mentries = new MapEntrySet();
-        }
-        return mentries;
-    }
-
-    /**
-     * An iterator on mkeys.
-     *
-     * <P>We simply override the
-     * {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()}
- methods (and possibly their type-specific counterparts) so that they
- return mkeys instead of mentries.
-     */
     private final class KeyIterator extends MapIterator implements Iterator<K> {
 
         public KeyIterator() {
@@ -687,22 +752,6 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
         }
     }
 
-    @Override
-    public final Set<K> keySet() {
-        if (mkeys == null) {
-            mkeys = new KeySet();
-        }
-        return mkeys;
-    }
-
-    /**
-     * An iterator on mvalues.
-     *
-     * <P>We simply override the
-     * {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()}
- methods (and possibly their type-specific counterparts) so that they
- return mvalues instead of mentries.
-     */
     private final class ValueIterator extends IntIterator {
 
         private final MapIterator delegate = new MapIterator();
@@ -725,203 +774,4 @@ public abstract class AHashLookup<K> extends Lookup<K> implements java.io.Serial
         }
     }
 
-    @Override
-    public final IntCollection values() {
-        if (mvalues == null) {
-            mvalues = new IntCollection() {
-                @Override
-                public IntIterator iterator() {
-                    return new ValueIterator();
-                }
-
-                @Override
-                public int size() {
-                    return size;
-                }
-
-                @Override
-                public boolean contains(int v) {
-                    return containsValue(v);
-                }
-
-                @Override
-                public void clear() {
-                    AHashLookup.this.clear();
-                }
-            };
-        }
-        return mvalues;
-    }
-
-    /**
-     * Rehashes the map, making the table as small as possible.
-     *
-     * <P>This method rehashes the table to the smallest size satisfying the
-     * load factor. It can be used when the set will not be changed anymore, so
-     * to optimize access speed and size.
-     *
-     * <P>If the table size is already the minimum possible, this method does
-     * nothing.
-     *
-     * @return true if there was enough memory to trim the map.
-     * @see #trim(int)
-     */
-    public final boolean trim() {
-        int l = HashCollection.arraysize(size, factor);
-        if (l >= n) {
-            return true;
-        }
-        try {
-            rehash(l);
-        } catch (OutOfMemoryError cantDoIt) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Rehashes this map if the table is too large.
-     *
-     * <P>Let <var>N</var> be the smallest table size that can hold
-     * <code>max(n,{@link #size()})</code> mentries, still satisfying the load
- factor. If the current table size is smaller than or equal to
- <var>N</var>, this method does nothing. Otherwise, it rehashes this map
-     * in a table of size
-     * <var>N</var>.
-     *
-     * <P>This method is useful when reusing maps. null null null null null     {@linkplain #clear() Clearing a
-	 * map} leaves the table size untouched. If you are reusing a map many
-     * times, you can call this method with a typical size to avoid keeping
-     * around a very large table just because of a few large transient maps.
-     *
-     * @param n the threshold for the trimming.
-     * @return true if there was enough memory to trim the map.
-     * @see #trim()
-     */
-    public final boolean trim(int n) {
-        int l = MathUtils.pow2next((int) Math.ceil(n / factor));
-        if (this.n <= l) {
-            return true;
-        }
-        try {
-            rehash(l);
-        } catch (OutOfMemoryError cantDoIt) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Resizes the map.
-     *
-     * <P>This method implements the basic rehashing strategy, and may be
-     * overriden by subclasses implementing different rehashing strategies
-     * (e.g., disk-based rehashing). However, you should not override this
-     * method unless you understand the internal workings of this class.
-     *
-     * @param newN the new size
-     */
-    @SuppressWarnings("unchecked")
-    protected final void rehash(int newN) {
-        int i = 0, pos;
-        boolean nused[] = this.used;
-        K ckey;
-        K ikeys[] = this.keys;
-        int ivalues[] = this.values;
-        int newMask = newN - 1;
-        K newKey[] = (K[]) new Object[newN];
-        int newValue[] = new int[newN];
-        boolean newUsed[] = new boolean[newN];
-        for (int j = size; j-- != 0;) {
-            while (!nused[ i]) {
-                i++;
-            }
-            ckey = ikeys[ i];
-            pos = HashUtils.murmurHash3(hashkey((K)ckey)) & newMask;
-            while (newUsed[ pos]) {
-                pos = (pos + 1) & newMask;
-            }
-            newUsed[ pos] = true;
-            newKey[ pos] = ckey;
-            newValue[ pos] = ivalues[ i];
-            i++;
-        }
-        n = newN;
-        mask = newMask;
-        maxFill = HashCollection.factorsize(n, factor);
-        this.keys = newKey;
-        this.values = newValue;
-        this.used = newUsed;
-    }
-
-    /**
-     * Returns a hash code for this map.
-     *
-     * This method overrides the generic method provided by the superclass.
-     * Since
-     * <code>equals()</code> is not overriden, it is important that the values
- returned by this method is the same values as the one returned by the
- overriden method.
-     *
-     * @return a hash code for this map.
-     */
-    @Override
-    public final int hashCode() {
-        int h = 0;
-        for (int j = size, i = 0, t = 0; j-- != 0;) {
-            while (!used[ i]) {
-                i++;
-            }
-            if (this != keys[ i]) {
-                t = hashkey((K)keys[i]);
-            }
-            t ^= values[i];
-            h += t;
-            i++;
-        }
-        return h;
-    }
-
-    @Override
-    public final boolean equals(Object object) {
-        return super.equals(object);
-    }
-    
-    private void writeObject(java.io.ObjectOutputStream ostream) throws java.io.IOException {
-        K ikeys[] = this.keys;
-        int ivalues[] = this.values;
-        MapIterator iterator = new MapIterator();
-        ostream.defaultWriteObject();
-        for (int j = size, element; j-- != 0;) {
-            element = iterator.nextEntry();
-            ostream.writeObject(ikeys[ element]);
-            ostream.writeInt(ivalues[ element]);
-        }
-    }
-
-    @SuppressWarnings({
-        "unchecked",
-        "MismatchedReadAndWriteOfArray"
-    })
-    private void readObject(java.io.ObjectInputStream istream) throws java.io.IOException, ClassNotFoundException {
-        istream.defaultReadObject();
-        n = HashCollection.arraysize(size, factor);
-        maxFill = HashCollection.factorsize(n, factor);
-        mask = n - 1;
-        K ikeys[] = this.keys = (K[]) new Object[n];
-        int ivalues[] = this.values = new int[n];
-        boolean iused[] = this.used = new boolean[n];
-        for (int i = size, pos; i-- != 0;) {
-            K ckey = (K) istream.readObject();
-            int cval = istream.readInt();
-            pos = HashUtils.murmurHash3(hashkey((K)ckey)) & mask;
-            while (iused[ pos]) {
-                pos = (pos + 1) & mask;
-            }
-            iused[pos] = true;
-            ikeys[pos] = ckey;
-            ivalues[pos] = cval;
-        }
-    }
-
 }

+ 2 - 2
assira/src/main/java/net/ranides/assira/collection/lookups/CustomLookup.java

@@ -155,12 +155,12 @@ public final class CustomLookup<K> extends AHashLookup<K> {
     }
 
     @Override
-    protected int hashkey(K key) {
+    protected int hash(K key) {
         return HashUtils.murmurHash3(strategy.hashCode(key));
     }
 
     @Override
-    protected boolean cmpkey(K key1, K key2) {
+    protected boolean compare(K key1, K key2) {
         return strategy.equals(key1, key2);
     }
 

+ 2 - 2
assira/src/main/java/net/ranides/assira/collection/lookups/HashLookup.java

@@ -127,12 +127,12 @@ public final class HashLookup<K> extends AHashLookup<K> {
     }
     
     @Override
-    protected int hashkey(K key) {
+    protected int hash(K key) {
         return key == null ? 0x87fcd5c : HashUtils.murmurHash3(key.hashCode());
     }
 
     @Override
-    protected boolean cmpkey(K key1, K key2) {
+    protected boolean compare(K key1, K key2) {
         return ValueUtils.equals(key1, key2);
     }
     

+ 2 - 2
assira/src/main/java/net/ranides/assira/collection/lookups/IdentLookup.java

@@ -129,12 +129,12 @@ public final class IdentLookup<K> extends AHashLookup<K> {
     }
     
     @Override
-    protected int hashkey(K key) {
+    protected int hash(K key) {
         return key == null ? 0x87fcd5c : HashUtils.murmurHash3(System.identityHashCode(key));
     }
 
     @Override
-    protected boolean cmpkey(K key1, K key2) {
+    protected boolean compare(K key1, K key2) {
         return key1 == key2; // NOPMD : identity
     }
 }

+ 2 - 1
assira/src/main/java/net/ranides/assira/collection/maps/AHashMap.java

@@ -612,7 +612,8 @@ public abstract class AHashMap<K,V> extends AMap<K, V> implements java.io.Serial
                 return false;
             }
             Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
-            return AHashMap.this.containsKey(entry.getKey());
+			int pos = ifind(entry.getKey());
+			return used[pos] && ValueUtils.equals(entry.getValue(), values[pos]);
         }
 
         @SuppressWarnings("unchecked")

Dosya farkı çok büyük olduğundan ihmal edildi
+ 377 - 514
assira/src/main/java/net/ranides/assira/collection/maps/IntHashMap.java