/** * Returns the hash code value for this map. The hash code of a map is defined to be the sum of * the hash codes of each entry in the map's <tt>entrySet()</tt> view. This ensures that * <tt>m1.equals(m2)</tt> implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two maps * <tt>m1</tt> and <tt>m2</tt>, as required by the general contract of {@link Object#hashCode}. * * <p> * This implementation iterates over <tt>entrySet()</tt>, calling * {@link java.util.Map.Entry#hashCode() hashCode()} on each element (entry) in the set, and * adding up the results. * * @return the hash code value for this map * @see java.util.Map.Entry#hashCode() * @see Object#equals(Object) * @see Set#equals(Object) */ public int hashCode() { int h = 0; Iterator<Entry> i = entrySet().iterator(); while (i.hasNext()) h += i.next().hashCode(); return h; }
/** * Associates the specified value with the specified key in this map. If the map previously * contained a mapping for the key, the old value is replaced. * * @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 <tt>key</tt>, or <tt>null</tt> if there was no * mapping for <tt>key</tt>. (A <tt>null</tt> return can also indicate that the map * previously associated <tt>null</tt> with <tt>key</tt>.) */ public int put(Object key, int value) { if (key == null) return putForNullKey(value); int hash = hash(hashingStrategy.hashCode(key)); int i = indexFor(hash, table.length); for (Entry e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || hashingStrategy.equals(k, key))) { int oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return 0; }
/** * Removes and returns the entry associated with the specified key in the IntHashMap. Returns null * if the IntHashMap contains no mapping for this key. */ Entry removeEntryForKey(Object key) { int hash = (key == null) ? 0 : hash(hashingStrategy.hashCode(key)); int i = indexFor(hash, table.length); Entry prev = table[i]; Entry e = prev; while (e != null) { Entry next = e.next; Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && hashingStrategy.equals(k, key)))) { modCount++; size--; if (prev == e) table[i] = next; else prev.next = next; e.recordRemoval(this); return e; } prev = e; e = next; } return e; }
/** * Special version of remove for EntrySet. */ Entry removeMapping(Object o) { if (!(o instanceof Entry)) return null; Entry entry = (Entry) o; Object key = entry.getKey(); int hash = (key == null) ? 0 : hash(hashingStrategy.hashCode(key)); int i = indexFor(hash, table.length); Entry prev = table[i]; Entry e = prev; while (e != null) { Entry next = e.next; if (e.hash == hash && e.equals(entry)) { modCount++; size--; if (prev == e) table[i] = next; else prev.next = next; e.recordRemoval(this); return e; } prev = e; e = next; } return e; }
/** * Returns a string representation of this map. The string representation consists of a list of * key-value mappings in the order returned by the map's <tt>entrySet</tt> view's iterator, * enclosed in braces (<tt>"{}"</tt>). Adjacent mappings are separated by the characters * <tt>", "</tt> (comma and space). Each key-value mapping is rendered as the key followed by an * equals sign (<tt>"="</tt>) followed by the associated value. Keys and values are converted to * strings as by {@link String#valueOf(Object)}. * * @return a string representation of this map */ public String toString() { Iterator<Entry> i = entrySet().iterator(); if (!i.hasNext()) return "{}"; StringBuilder sb = new StringBuilder(); sb.append('{'); for (;;) { Entry e = i.next(); Object key = e.getKey(); int value = e.getValue(); sb.append(key == this ? "(this Map)" : key); sb.append('='); sb.append(value); if (!i.hasNext()) return sb.append('}').toString(); sb.append(", "); } }
/** * Save the state of the <tt>HashMap</tt> instance to a stream (i.e., serialize it). * * @serialData The <i>capacity</i> of the IntHashMap (the length of the bucket array) is emitted * (int), followed by the <i>size</i> (an int, the number of key-value mappings), * followed by the key (Object) and value (Object) for each key-value mapping. The * key-value mappings are emitted in no particular order. */ private void writeObject(java.io.ObjectOutputStream s) throws IOException { Iterator<Entry> i = (size > 0) ? entrySet0().iterator() : null; // Write out the threshold, loadfactor, and any hidden stuff s.defaultWriteObject(); // Write out number of buckets s.writeInt(table.length); // Write out size (number of Mappings) s.writeInt(size); // Write out keys and values (alternating) if (i != null) { while (i.hasNext()) { Entry e = i.next(); s.writeObject(e.getKey()); s.writeInt(e.getValue()); } } }
@Override public void toData(DataOutput out) throws IOException { DataSerializer.writeObject(this.elementType, out); out.writeInt(this.size()); this.writeNumNulls(out); // TODO:Asif: Should we actually pass the limit in serialization? // For the time being not passing , assuming PR Has parsed // it // out.writeInt(this.limit); int numLeft = this.size() - this.numNulls; for (Iterator<Entry> itr = this.map.entrySet().iterator(); itr.hasNext() && numLeft > 0;) { Entry entry = itr.next(); Object key = entry.getKey(); DataSerializer.writeObject(key, out); int occurrence = entry.getValue(); if (numLeft < occurrence) { occurrence = numLeft; } out.writeInt(occurrence); numLeft -= occurrence; } }
/** * Offloaded version of put for null keys */ private int putForNullKey(int value) { for (Entry e = table[0]; e != null; e = e.next) { if (e.key == null) { int oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(0, null, value, 0); return 0; }
@Override protected Object keyFromEntry(Object entry) { return ((Entry) entry).getKey(); }
@Override public Object next() { return nextEntry().getKey(); } }
@Override protected Integer valueFromEntry(Object entry) { return ((Entry) entry).getValue(); } }
/** * Like addEntry except that this version is used when creating entries as part of Map * construction or "pseudo-construction" (cloning, deserialization). This version needn't worry * about resizing the table. * * Subclass overrides this to alter the behavior of IntHashMap(Map), clone, and readObject. */ void createEntry(int hash, Object key, int value, int bucketIndex) { Entry e = table[bucketIndex]; table[bucketIndex] = new Entry(hash, key, value, e); size++; }
/** * Adds a new entry with the specified key, value and hash code to the specified bucket. It is the * responsibility of this method to resize the table if appropriate. * * Subclass overrides this to alter the behavior of put method. */ void addEntry(int hash, Object key, int value, int bucketIndex) { Entry e = table[bucketIndex]; table[bucketIndex] = new Entry(hash, key, value, e); if (size++ >= threshold) resize(2 * table.length); }