hashtable.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 1,058 行 · 第 1/3 页
JAVA
1,058 行
}
/**
* Returns true if the supplied object <code>equals()</code> a key
* in this Hashtable.
*
* @param key the key to search for in this Hashtable
* @return true if the key is in the table
* @throws NullPointerException if key is null
* @see #containsValue(Object)
*/
public synchronized boolean containsKey(Object key) {
int idx = hash(key);
HashEntry e = buckets[idx];
while (e != null) {
if (key.equals(e.key))
return true;
e = e.next;
}
return false;
}
/**
* Return the value in this Hashtable associated with the supplied key,
* or <code>null</code> if the key maps to nothing.
*
* @param key the key for which to fetch an associated value
* @return what the key maps to, if present
* @throws NullPointerException if key is null
* @see #put(Object, Object)
* @see #containsKey(Object)
*/
public synchronized Object get(Object key) {
int idx = hash(key);
HashEntry e = buckets[idx];
while (e != null) {
if (key.equals(e.key))
return e.value;
e = e.next;
}
return null;
}
/**
* Puts the supplied value into the Map, mapped by the supplied key.
* Neither parameter may be null. The value may be retrieved by any
* object which <code>equals()</code> this key.
*
* @param key the key used to locate the value
* @param value the value to be stored in the table
* @return the prior mapping of the key, or null if there was none
* @throws NullPointerException if key or value is null
* @see #get(Object)
* @see Object#equals(Object)
*/
public synchronized Object put(Object key, Object value) {
int idx = hash(key);
HashEntry e = buckets[idx];
// Check if value is null since it is not permitted.
if (value == null)
throw new NullPointerException();
while (e != null) {
if (key.equals(e.key)) {
// Bypass e.setValue, since we already know value is non-null.
Object r = e.value;
e.value = value;
return r;
} else {
e = e.next;
}
}
// At this point, we know we need to add a new entry.
modCount++;
if (++size > threshold) {
rehash();
// Need a new hash value to suit the bigger table.
idx = hash(key);
}
e = new HashEntry(key, value);
e.next = buckets[idx];
buckets[idx] = e;
return null;
}
/**
* Removes from the table and returns the value which is mapped by the
* supplied key. If the key maps to nothing, then the table remains
* unchanged, and <code>null</code> is returned.
*
* @param key the key used to locate the value to remove
* @return whatever the key mapped to, if present
*/
public synchronized Object remove(Object key) {
int idx = hash(key);
HashEntry e = buckets[idx];
HashEntry last = null;
while (e != null) {
if (key.equals(e.key)) {
modCount++;
if (last == null)
buckets[idx] = e.next;
else
last.next = e.next;
size--;
return e.value;
}
last = e;
e = e.next;
}
return null;
}
/**
* Copies all elements of the given map into this hashtable. However, no
* mapping can contain null as key or value. If this table already has
* a mapping for a key, the new mapping replaces the current one.
*
* @param m the map to be hashed into this
* @throws NullPointerException if m is null, or contains null keys or values
*/
public synchronized void putAll(Map m) {
Iterator itr = m.entrySet().iterator();
for (int msize = m.size(); msize > 0; msize--) {
Map.Entry e = (Map.Entry) itr.next();
// Optimize in case the Entry is one of our own.
if (e instanceof AbstractMap.BasicMapEntry) {
AbstractMap.BasicMapEntry entry = (AbstractMap.BasicMapEntry) e;
put(entry.key, entry.value);
} else {
put(e.getKey(), e.getValue());
}
}
}
/**
* Clears the hashtable so it has no keys. This is O(1).
*/
public synchronized void clear() {
if (size > 0) {
modCount++;
Arrays.fill(buckets, null);
size = 0;
}
}
/**
* Returns a shallow clone of this Hashtable. The Map itself is cloned,
* but its contents are not. This is O(n).
*
* @return the clone
*/
public synchronized Object clone() {
Hashtable copy = null;
try {
copy = (Hashtable) super.clone();
} catch (CloneNotSupportedException x) {
// This is impossible.
}
copy.buckets = new HashEntry[buckets.length];
copy.putAllInternal(this);
// Clear the caches.
copy.keys = null;
copy.values = null;
copy.entries = null;
return copy;
}
/**
* Converts this Hashtable to a String, surrounded by braces, and with
* key/value pairs listed with an equals sign between, separated by a
* comma and space. For example, <code>"{a=1, b=2}"</code>.<p>
*
* NOTE: if the <code>toString()</code> method of any key or value
* throws an exception, this will fail for the same reason.
*
* @return the string representation
*/
public synchronized String toString() {
// Since we are already synchronized, and entrySet().iterator()
// would repeatedly re-lock/release the monitor, we directly use the
// unsynchronized HashIterator instead.
Iterator entries = new HashIterator(ENTRIES);
StringBuffer r = new StringBuffer("{");
for (int pos = size; pos > 0; pos--) {
r.append(entries.next());
if (pos > 1)
r.append(", ");
}
r.append("}");
return r.toString();
}
/**
* Returns a "set view" of this Hashtable's keys. The set is backed by
* the hashtable, so changes in one show up in the other. The set supports
* element removal, but not element addition. The set is properly
* synchronized on the original hashtable. Sun has not documented the
* proper interaction of null with this set, but has inconsistent behavior
* in the JDK. Therefore, in this implementation, contains, remove,
* containsAll, retainAll, removeAll, and equals just ignore a null key
* rather than throwing a {@link NullPointerException}.
*
* @return a set view of the keys
* @see #values()
* @see #entrySet()
* @since 1.2
*/
public Set keySet() {
if (keys == null) {
// Create a synchronized AbstractSet with custom implementations of
// those methods that can be overridden easily and efficiently.
Set r = new AbstractSet() {
public int size() {
return size;
}
public Iterator iterator() {
return new HashIterator(KEYS);
}
public void clear() {
Hashtable.this.clear();
}
public boolean contains(Object o) {
if (o == null)
return false;
return containsKey(o);
}
public boolean remove(Object o) {
return Hashtable.this.remove(o) != null;
}
};
// We must specify the correct object to synchronize upon, hence the
// use of a non-public API
keys = new Collections.SynchronizedSet(this, r);
}
return keys;
}
/**
* Returns a "collection view" (or "bag view") of this Hashtable's values.
* The collection is backed by the hashtable, so changes in one show up
* in the other. The collection supports element removal, but not element
* addition. The collection is properly synchronized on the original
* hashtable. Sun has not documented the proper interaction of null with
* this set, but has inconsistent behavior in the JDK. Therefore, in this
* implementation, contains, remove, containsAll, retainAll, removeAll, and
* equals just ignore a null value rather than throwing a
* {@link NullPointerException}.
*
* @return a bag view of the values
* @see #keySet()
* @see #entrySet()
* @since 1.2
*/
public Collection values() {
if (values == null) {
// We don't bother overriding many of the optional methods, as doing so
// wouldn't provide any significant performance advantage.
Collection r = new AbstractCollection() {
public int size() {
return size;
}
public Iterator iterator() {
return new HashIterator(VALUES);
}
public void clear() {
Hashtable.this.clear();
}
};
// We must specify the correct object to synchronize upon, hence the
// use of a non-public API
values = new Collections.SynchronizedCollection(this, r);
}
return values;
}
/**
* Returns a "set view" of this Hashtable's entries. The set is backed by
* the hashtable, so changes in one show up in the other. The set supports
* element removal, but not element addition. The set is properly
* synchronized on the original hashtable. Sun has not documented the
* proper interaction of null with this set, but has inconsistent behavior
* in the JDK. Therefore, in this implementation, contains, remove,
* containsAll, retainAll, removeAll, and equals just ignore a null entry,
* or an entry with a null key or value, rather than throwing a
* {@link NullPointerException}. However, calling entry.setValue(null)
* will fail.
* <p>
*
* Note that the iterators for all three views, from keySet(), entrySet(),
* and values(), traverse the hashtable in the same sequence.
*
* @return a set view of the entries
* @see #keySet()
* @see #values()
* @see Map.Entry
* @since 1.2
*/
public Set entrySet() {
if (entries == null) {
// Create an AbstractSet with custom implementations of those methods
// that can be overridden easily and efficiently.
Set r = new AbstractSet() {
public int size() {
return size;
}
public Iterator iterator() {
return new HashIterator(ENTRIES);
}
public void clear() {
Hashtable.this.clear();
}
public boolean contains(Object o) {
return getEntry(o) != null;
}
public boolean remove(Object o) {
HashEntry e = getEntry(o);
if (e != null) {
Hashtable.this.remove(e.key);
return true;
}
return false;
}
};
// We must specify the correct object to synchronize upon, hence the
// use of a non-public API
entries = new Collections.SynchronizedSet(this, r);
}
return entries;
}
/**
* Returns true if this Hashtable equals the supplied Object <code>o</code>.
* As specified by Map, this is:
* <code>
* (o instanceof Map) && entrySet().equals(((Map) o).entrySet());
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?