/**
   * {@inheritDoc}
   *
   * <p>This method will, on a best-effort basis, throw a {@link
   * java.util.ConcurrentModificationException} if the remapping function modified this map during
   * computation.
   *
   * @throws ConcurrentModificationException if it is detected that the remapping function modified
   *     this map
   */
  @Override
  public synchronized V computeIfPresent(
      K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
    Objects.requireNonNull(remappingFunction);

    Entry<?, ?> tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    @SuppressWarnings("unchecked")
    Entry<K, V> e = (Entry<K, V>) tab[index];
    for (Entry<K, V> prev = null; e != null; prev = e, e = e.next) {
      if (e.hash == hash && e.key.equals(key)) {
        int mc = modCount;
        V newValue = remappingFunction.apply(key, e.value);
        if (mc != modCount) {
          throw new ConcurrentModificationException();
        }
        if (newValue == null) {
          if (prev != null) {
            prev.next = e.next;
          } else {
            tab[index] = e.next;
          }
          modCount = mc + 1;
          count--;
        } else {
          e.value = newValue;
        }
        return newValue;
      }
    }
    return null;
  }
Пример #2
0
  /**
   * Maps the specified <code>key</code> to the specified <code>value</code> in this hashtable.
   * Neither the key nor the value can be <code>null</code>.
   *
   * <p>The value can be retrieved by calling the <code>get</code> method with a key that is equal
   * to the original key.
   *
   * @param key the hashtable key
   * @param value the value
   * @return the previous value of the specified key in this hashtable, or <code>null</code> if it
   *     did not have one
   * @exception NullPointerException if the key or value is <code>null</code>
   * @see Object#equals(Object)
   * @see #get(Object)
   */
  public synchronized V put(K key, V value) {
    // Make sure the value is not null
    if (value == null) {
      throw new NullPointerException();
    }

    // Makes sure the key is not already in the hashtable.
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry<K, V> e = tab[index]; e != null; e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        V old = e.value;
        e.value = value;
        return old;
      }
    }

    modCount++;
    if (count >= threshold) {
      // Rehash the table if the threshold is exceeded
      rehash();

      tab = table;
      index = (hash & 0x7FFFFFFF) % tab.length;
    }

    // Creates the new entry.
    Entry<K, V> e = tab[index];
    tab[index] = new Entry<>(hash, key, value, e);
    count++;
    return null;
  }
Пример #3
0
 public int compareTo(Entry e) {
   double v1 = value(), v2 = e.value();
   if (v1 < v2) {
     return -1;
   }
   if (v1 > v2) {
     return 1;
   }
   return 0;
 }
Пример #4
0
 /** Offloaded version of put for null keys */
 private V putForNullKey(V value) {
   for (Entry<K, V> e = table[0]; e != null; e = e.next) {
     if (e.key == null) {
       V oldValue = e.value;
       e.value = value;
       e.recordAccess(this);
       return oldValue;
     }
   }
   modCount++;
   addEntry(0, null, value, 0);
   return null;
 }
 @Override
 public synchronized V replace(K key, V value) {
   Objects.requireNonNull(value);
   Entry<?, ?> tab[] = table;
   int hash = key.hashCode();
   int index = (hash & 0x7FFFFFFF) % tab.length;
   @SuppressWarnings("unchecked")
   Entry<K, V> e = (Entry<K, V>) tab[index];
   for (; e != null; e = e.next) {
     if ((e.hash == hash) && e.key.equals(key)) {
       V oldValue = e.value;
       e.value = value;
       return oldValue;
     }
   }
   return null;
 }
Пример #6
0
  /**
   * 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 V put(K key, V value) {
    if (key == null) return putForNullKey(value);
    int hash = hash(key);
    int i = indexFor(hash, table.length);
    for (Entry<K, V> e = table[i]; e != null; e = e.next) {
      Object k;
      if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
        V oldValue = e.value;
        e.value = value;
        e.recordAccess(this);
        return oldValue;
      }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
  }
  @SuppressWarnings("unchecked")
  @Override
  public synchronized void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
    Objects.requireNonNull(function); // explicit check required in case
    // table is empty.
    final int expectedModCount = modCount;

    Entry<K, V>[] tab = (Entry<K, V>[]) table;
    for (Entry<K, V> entry : tab) {
      while (entry != null) {
        entry.value = Objects.requireNonNull(function.apply(entry.key, entry.value));
        entry = entry.next;

        if (expectedModCount != modCount) {
          throw new ConcurrentModificationException();
        }
      }
    }
  }
Пример #8
0
  /**
   * This method is used instead of put by constructors and pseudoconstructors (clone, readObject).
   * It does not resize the table, check for comodification, etc. It calls createEntry rather than
   * addEntry.
   */
  private void putForCreate(K key, V value) {
    int hash = null == key ? 0 : hash(key);
    int i = indexFor(hash, table.length);

    /**
     * Look for preexisting entry for key. This will never happen for clone or deserialize. It will
     * only happen for construction if the input Map is a sorted map whose ordering is inconsistent
     * w/ equals.
     */
    for (Entry<K, V> e = table[i]; e != null; e = e.next) {
      Object k;
      if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {
        e.value = value;
        return;
      }
    }

    createEntry(hash, key, value, i);
  }
Пример #9
0
 /**
  * Removes the key (and its corresponding value) from this hashtable. This method does nothing if
  * the key is not in the hashtable.
  *
  * @param key the key that needs to be removed
  * @return the value to which the key had been mapped in this hashtable, or <code>null</code> if
  *     the key did not have a mapping
  * @throws NullPointerException if the key is <code>null</code>
  */
 public synchronized V remove(Object key) {
   Entry tab[] = table;
   int hash = key.hashCode();
   int index = (hash & 0x7FFFFFFF) % tab.length;
   for (Entry<K, V> e = tab[index], prev = null; e != null; prev = e, e = e.next) {
     if ((e.hash == hash) && e.key.equals(key)) {
       modCount++;
       if (prev != null) {
         prev.next = e.next;
       } else {
         tab[index] = e.next;
       }
       count--;
       V oldValue = e.value;
       e.value = null;
       return oldValue;
     }
   }
   return null;
 }
 @Override
 public synchronized boolean replace(K key, V oldValue, V newValue) {
   Objects.requireNonNull(oldValue);
   Objects.requireNonNull(newValue);
   Entry<?, ?> tab[] = table;
   int hash = key.hashCode();
   int index = (hash & 0x7FFFFFFF) % tab.length;
   @SuppressWarnings("unchecked")
   Entry<K, V> e = (Entry<K, V>) tab[index];
   for (; e != null; e = e.next) {
     if ((e.hash == hash) && e.key.equals(key)) {
       if (e.value.equals(oldValue)) {
         e.value = newValue;
         return true;
       } else {
         return false;
       }
     }
   }
   return false;
 }
Пример #11
0
    public boolean remove(Object o) {
      if (!(o instanceof Map.Entry)) return false;
      Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
      K key = entry.getKey();
      Entry[] tab = table;
      int hash = key.hashCode();
      int index = (hash & 0x7FFFFFFF) % tab.length;

      for (Entry<K, V> e = tab[index], prev = null; e != null; prev = e, e = e.next) {
        if (e.hash == hash && e.equals(entry)) {
          modCount++;
          if (prev != null) prev.next = e.next;
          else tab[index] = e.next;

          count--;
          e.value = null;
          return true;
        }
      }
      return false;
    }
 /**
  * Removes the key (and its corresponding value) from this hashtable. This method does nothing if
  * the key is not in the hashtable.
  *
  * @param key the key that needs to be removed
  * @return the value to which the key had been mapped in this hashtable, or {@code null} if the
  *     key did not have a mapping
  * @throws NullPointerException if the key is {@code null}
  */
 public synchronized V remove(Object key) {
   Entry<?, ?> tab[] = table;
   int hash = key.hashCode();
   int index = (hash & 0x7FFFFFFF) % tab.length;
   @SuppressWarnings("unchecked")
   Entry<K, V> e = (Entry<K, V>) tab[index];
   for (Entry<K, V> prev = null; e != null; prev = e, e = e.next) {
     if ((e.hash == hash) && e.key.equals(key)) {
       if (prev != null) {
         prev.next = e.next;
       } else {
         tab[index] = e.next;
       }
       modCount++;
       count--;
       V oldValue = e.value;
       e.value = null;
       return oldValue;
     }
   }
   return null;
 }
  @Override
  public synchronized V putIfAbsent(K key, V value) {
    Objects.requireNonNull(value);

    // Makes sure the key is not already in the hashtable.
    Entry<?, ?> tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    @SuppressWarnings("unchecked")
    Entry<K, V> entry = (Entry<K, V>) tab[index];
    for (; entry != null; entry = entry.next) {
      if ((entry.hash == hash) && entry.key.equals(key)) {
        V old = entry.value;
        if (old == null) {
          entry.value = value;
        }
        return old;
      }
    }

    addEntry(hash, key, value, index);
    return null;
  }
    public boolean remove(Object o) {
      if (!(o instanceof Map.Entry)) return false;
      Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
      Object key = entry.getKey();
      Entry<?, ?>[] tab = table;
      int hash = key.hashCode();
      int index = (hash & 0x7FFFFFFF) % tab.length;

      @SuppressWarnings("unchecked")
      Entry<K, V> e = (Entry<K, V>) tab[index];
      for (Entry<K, V> prev = null; e != null; prev = e, e = e.next) {
        if (e.hash == hash && e.equals(entry)) {
          if (prev != null) prev.next = e.next;
          else tab[index] = e.next;

          e.value = null; // clear for gc.
          modCount++;
          count--;
          return true;
        }
      }
      return false;
    }
  /**
   * Maps the specified {@code key} to the specified {@code value} in this hashtable. Neither the
   * key nor the value can be {@code null}.
   *
   * <p>The value can be retrieved by calling the {@code get} method with a key that is equal to the
   * original key.
   *
   * @param key the hashtable key
   * @param value the value
   * @return the previous value of the specified key in this hashtable, or {@code null} if it did
   *     not have one
   * @exception NullPointerException if the key or value is {@code null}
   * @see Object#equals(Object)
   * @see #get(Object)
   */
  public synchronized V put(K key, V value) {
    // Make sure the value is not null
    if (value == null) {
      throw new NullPointerException();
    }

    // Makes sure the key is not already in the hashtable.
    Entry<?, ?> tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    @SuppressWarnings("unchecked")
    Entry<K, V> entry = (Entry<K, V>) tab[index];
    for (; entry != null; entry = entry.next) {
      if ((entry.hash == hash) && entry.key.equals(key)) {
        V old = entry.value;
        entry.value = value;
        return old;
      }
    }

    addEntry(hash, key, value, index);
    return null;
  }
  @Override
  public synchronized boolean remove(Object key, Object value) {
    Objects.requireNonNull(value);

    Entry<?, ?> tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    @SuppressWarnings("unchecked")
    Entry<K, V> e = (Entry<K, V>) tab[index];
    for (Entry<K, V> prev = null; e != null; prev = e, e = e.next) {
      if ((e.hash == hash) && e.key.equals(key) && e.value.equals(value)) {
        if (prev != null) {
          prev.next = e.next;
        } else {
          tab[index] = e.next;
        }
        e.value = null; // clear for gc
        modCount++;
        count--;
        return true;
      }
    }
    return false;
  }