⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 identityhashmap.java

📁 this gcc-g++-3.3.1.tar.gz is a source file of gcc, you can learn more about gcc through this codes f
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
  }  /**   * Puts the supplied value into the Map, mapped by the supplied key.   * The value may be retrieved by any object which <code>equals()</code>   * this key. NOTE: Since the prior value could also be null, you must   * first use containsKey if you want to see if you are replacing the   * key's mapping.  Unlike normal maps, this tests for the key   * with <code>entry == key</code> instead of   * <code>entry == null ? key == null : entry.equals(key)</code>.   *   * @param key the key used to locate the value   * @param value the value to be stored in the HashMap   * @return the prior mapping of the key, or null if there was none   * @see #get(Object)   */  public Object put(Object key, Object value)  {    // Rehash if the load factor is too high.    if (size > threshold)      {        Object[] old = table;        // This isn't necessarily prime, but it is an odd number of key/value        // slots, which has a higher probability of fewer collisions.        table = new Object[old.length << 1 + 2];        Arrays.fill(table, emptyslot);        size = 0;        threshold = (table.length >>> 3) * 3;        for (int i = old.length - 2; i >= 0; i -= 2)          {            Object oldkey = old[i];            if (oldkey != tombstone && oldkey != emptyslot)              // Just use put.  This isn't very efficient, but it is ok.              put(oldkey, old[i + 1]);          }      }    int h = hash(key);    if (table[h] == key)      {        Object r = table[h + 1];        table[h + 1] = value;        return r;      }    // At this point, we add a new mapping.    modCount++;    size++;    table[h] = key;    table[h + 1] = value;    return null;  }  /**   * Copies all of the mappings from the specified map to this. If a key   * is already in this map, its value is replaced.   *   * @param m the map to copy   * @throws NullPointerException if m is null   */  public void putAll(Map m)  {    // Why did Sun specify this one? The superclass does the right thing.    super.putAll(m);  }  /**   * Removes from the HashMap and returns the value which is mapped by   * the supplied key. If the key maps to nothing, then the HashMap   * remains unchanged, and <code>null</code> is returned.   *   * NOTE: Since the value could also be null, you must use   * containsKey to see if you are actually removing a mapping.   * Unlike normal maps, this tests for the key with <code>entry ==   * key</code> instead of <code>entry == null ? key == null :   * entry.equals(key)</code>.   *   * @param key the key used to locate the value to remove   * @return whatever the key mapped to, if present   */  public Object remove(Object key)  {    int h = hash(key);    if (table[h] == key)      {        modCount++;        size--;        Object r = table[h + 1];        table[h] = tombstone;        table[h + 1] = tombstone;        return r;      }    return null;  }  /**   * Returns the number of kay-value mappings currently in this Map   * @return the size   */  public int size()  {    return size;  }  /**   * Returns a "collection view" (or "bag view") of this Map's values.   * The collection is backed by the Map, so changes in one show up   * in the other.  The collection supports element removal, but not element   * addition.   * <p>   *   * <em>The semantics of this set are different from the contract of   * Collection in order to make IdentityHashMap work.  This means that   * while you can compare these objects between IdentityHashMaps, comparing   * them with regular sets is likely to have undefined behavior.</em>   * Likewise, contains and remove go by == instead of equals().   * <p>   *   * @return a bag view of the values   * @see #keySet()   * @see #entrySet()   */  public Collection values()  {    if (values == null)      values = new AbstractCollection()      {        public int size()        {          return size;        }        public Iterator iterator()        {          return new IdentityIterator(VALUES);        }        public void clear()        {          IdentityHashMap.this.clear();        }        public boolean remove(Object o)        {          for (int i = table.length - 1; i > 0; i -= 2)            if (table[i] == o)              {                modCount++;                table[i - 1] = tombstone;                table[i] = tombstone;                size--;                return true;              }          return false;        }      };    return values;  }  /**   * Helper method which computes the hash code, then traverses the table   * until it finds the key, or the spot where the key would go.   *   * @param key the key to check   * @return the index where the key belongs   * @see #IdentityHashMap(int)   * @see #put(Object, Object)   */  // Package visible for use by nested classes.  int hash(Object key)  {    // Implementation note: it is feasible for the table to have no    // emptyslots, if it is full with entries and tombstones, so we must    // remember where we started. If we encounter the key or an emptyslot,    // we are done.  If we encounter a tombstone, the key may still be in    // the array.  If we don't encounter the key, we use the first emptyslot    // or tombstone we encountered as the location where the key would go.    // By requiring at least 2 key/value slots, and rehashing at 75%    // capacity, we guarantee that there will always be either an emptyslot    // or a tombstone somewhere in the table.    int h = Math.abs(System.identityHashCode(key) % (table.length >> 1)) << 1;    int del = -1;    int save = h;    do      {        if (table[h] == key)          return h;        if (table[h] == emptyslot)          break;        if (table[h] == tombstone && del < 0)          del = h;        h -= 2;        if (h < 0)          h = table.length - 2;      }    while (h != save);    return del < 0 ? h : del;  }  /**   * This class allows parameterized iteration over IdentityHashMaps.  Based   * on its construction, it returns the key or value of a mapping, or   * creates the appropriate Map.Entry object with the correct fail-fast   * semantics and identity comparisons.   *   * @author Tom Tromey <tromey@redhat.com>   * @author Eric Blake <ebb9@email.byu.edu>   */  private final class IdentityIterator implements Iterator  {    /**     * The type of this Iterator: {@link #KEYS}, {@link #VALUES},     * or {@link #ENTRIES}.     */    final int type;    /** The number of modifications to the backing Map that we know about. */    int knownMod = modCount;    /** The number of elements remaining to be returned by next(). */    int count = size;    /** Location in the table. */    int loc = table.length;    /**     * Construct a new Iterator with the supplied type.     * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}     */    IdentityIterator(int type)    {      this.type = type;    }    /**     * Returns true if the Iterator has more elements.     * @return true if there are more elements     * @throws ConcurrentModificationException if the Map was modified     */    public boolean hasNext()    {      if (knownMod != modCount)        throw new ConcurrentModificationException();      return count > 0;    }    /**     * Returns the next element in the Iterator's sequential view.     * @return the next element     * @throws ConcurrentModificationException if the Map was modified     * @throws NoSuchElementException if there is none     */    public Object next()    {      if (knownMod != modCount)        throw new ConcurrentModificationException();      if (count == 0)        throw new NoSuchElementException();      count--;      Object key;      do        {          loc -= 2;          key = table[loc];        }      while (key == emptyslot || key == tombstone);      return type == KEYS ? key : (type == VALUES ? table[loc + 1]                                   : new IdentityEntry(loc));    }    /**     * Removes from the backing Map the last element which was fetched     * with the <code>next()</code> method.     *     * @throws ConcurrentModificationException if the Map was modified     * @throws IllegalStateException if called when there is no last element     */    public void remove()    {      if (knownMod != modCount)        throw new ConcurrentModificationException();      if (loc == table.length || table[loc] == tombstone)        throw new IllegalStateException();      modCount++;      size--;      table[loc] = tombstone;      table[loc + 1] = tombstone;      knownMod++;    }  } // class IdentityIterator  /**   * This class provides Map.Entry objects for IdentityHashMaps.  The entry   * is fail-fast, and will throw a ConcurrentModificationException if   * the underlying map is modified, or if remove is called on the iterator   * that generated this object.  It is identity based, so it violates   * the general contract of Map.Entry, and is probably unsuitable for   * comparison to normal maps; but it works among other IdentityHashMaps.   *   * @author Eric Blake <ebb9@email.byu.edu>   */  private final class IdentityEntry implements Map.Entry  {    /** The location of this entry. */    final int loc;    /** The number of modifications to the backing Map that we know about. */    final int knownMod = modCount;    /**     * Constructs the Entry.     *     * @param loc the location of this entry in table     */    IdentityEntry(int loc)    {      this.loc = loc;    }    /**     * Compares the specified object with this entry, using identity     * semantics. Note that this can lead to undefined results with     * Entry objects created by normal maps.     *     * @param o the object to compare     * @return true if it is equal     * @throws ConcurrentModificationException if the entry was invalidated     *         by modifying the Map or calling Iterator.remove()     */    public boolean equals(Object o)    {      if (knownMod != modCount || table[loc] == tombstone)        throw new ConcurrentModificationException();      if (! (o instanceof Map.Entry))        return false;      Map.Entry e = (Map.Entry) o;      return table[loc] == e.getKey() && table[loc + 1] == e.getValue();    }    /**     * Returns the key of this entry.     *     * @return the key     * @throws ConcurrentModificationException if the entry was invalidated     *         by modifying the Map or calling Iterator.remove()     */    public Object getKey()    {      if (knownMod != modCount || table[loc] == tombstone)        throw new ConcurrentModificationException();      return table[loc];    }    /**     * Returns the value of this entry.     *     * @return the value     * @throws ConcurrentModificationException if the entry was invalidated     *         by modifying the Map or calling Iterator.remove()     */    public Object getValue()    {      if (knownMod != modCount || table[loc] == tombstone)        throw new ConcurrentModificationException();      return table[loc + 1];    }    /**     * Returns the hashcode of the entry, using identity semantics.     * Note that this can lead to undefined results with Entry objects     * created by normal maps.     *     * @return the hash code     * @throws ConcurrentModificationException if the entry was invalidated     *         by modifying the Map or calling Iterator.remove()     */    public int hashCode()    {      if (knownMod != modCount || table[loc] == tombstone)        throw new ConcurrentModificationException();      return (System.identityHashCode(table[loc])              ^ System.identityHashCode(table[loc + 1]));    }    /**     * Replaces the value of this mapping, and returns the old value.     *     * @param value the new value     * @return the old value     * @throws ConcurrentModificationException if the entry was invalidated     *         by modifying the Map or calling Iterator.remove()     */    public Object setValue(Object value)    {      if (knownMod != modCount || table[loc] == tombstone)        throw new ConcurrentModificationException();      Object r = table[loc + 1];      table[loc + 1] = value;      return r;    }    /**     * This provides a string representation of the entry. It is of the form     * "key=value", where string concatenation is used on key and value.     *     * @return the string representation     * @throws ConcurrentModificationException if the entry was invalidated     *         by modifying the Map or calling Iterator.remove()     */    public final String toString()    {      if (knownMod != modCount || table[loc] == tombstone)        throw new ConcurrentModificationException();      return table[loc] + "=" + table[loc + 1];    }  } // class IdentityEntry  /**   * Reads the object from a serial stream.   *   * @param s the stream to read from   * @throws ClassNotFoundException if the underlying stream fails   * @throws IOException if the underlying stream fails   * @serialData expects the size (int), followed by that many key (Object)   *             and value (Object) pairs, with the pairs in no particular   *             order   */  private void readObject(ObjectInputStream s)    throws IOException, ClassNotFoundException  {    s.defaultReadObject();    int num = s.readInt();    table = new Object[Math.max(num << 1, DEFAULT_CAPACITY) << 1];    // Read key/value pairs.    while (--num >= 0)      put(s.readObject(), s.readObject());  }  /**   * Writes the object to a serial stream.   *   * @param s the stream to write to   * @throws IOException if the underlying stream fails   * @serialData outputs the size (int), followed by that many key (Object)   *             and value (Object) pairs, with the pairs in no particular   *             order   */  private void writeObject(ObjectOutputStream s)    throws IOException  {    s.defaultWriteObject();    s.writeInt(size);    for (int i = table.length - 2; i >= 0; i -= 2)      {        Object key = table[i];        if (key != tombstone && key != emptyslot)          {            s.writeObject(key);            s.writeObject(table[i + 1]);          }      }  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -