1 |
/* Hashtable.java -- a class providing a basic hashtable data structure, |
/* Hashtable.java -- a class providing a basic hashtable data structure, |
2 |
mapping Object --> Object |
mapping Object --> Object |
3 |
Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. |
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
6 |
|
|
102 |
public class Hashtable extends Dictionary |
public class Hashtable extends Dictionary |
103 |
implements Map, Cloneable, Serializable |
implements Map, Cloneable, Serializable |
104 |
{ |
{ |
|
// WARNING: Hashtable is a CORE class in the bootstrap cycle. See the |
|
|
// comments in vm/reference/java/lang/Runtime for implications of this fact. |
|
|
|
|
105 |
/** Default number of buckets. This is the value the JDK 1.3 uses. Some |
/** Default number of buckets. This is the value the JDK 1.3 uses. Some |
106 |
* early documentation specified this value as 101. That is incorrect. |
* early documentation specified this value as 101. That is incorrect. |
107 |
*/ |
*/ |
176 |
* pair. A Hashtable Entry is identical to a HashMap Entry, except that |
* pair. A Hashtable Entry is identical to a HashMap Entry, except that |
177 |
* `null' is not allowed for keys and values. |
* `null' is not allowed for keys and values. |
178 |
*/ |
*/ |
179 |
private static final class HashEntry extends AbstractMap.BasicMapEntry |
private static final class HashEntry extends BasicMapEntry |
180 |
{ |
{ |
181 |
/** The next entry in the linked list. */ |
/** The next entry in the linked list. */ |
182 |
HashEntry next; |
HashEntry next; |
322 |
* <code>containsValue()</code>, and is O(n). |
* <code>containsValue()</code>, and is O(n). |
323 |
* <p> |
* <p> |
324 |
* |
* |
|
* Note: this is one of the <i>old</i> Hashtable methods which does |
|
|
* not like null values; it throws NullPointerException if the |
|
|
* supplied parameter is null. |
|
|
* |
|
325 |
* @param value the value to search for in this Hashtable |
* @param value the value to search for in this Hashtable |
326 |
* @return true if at least one key maps to the value |
* @return true if at least one key maps to the value |
327 |
* @throws NullPointerException if <code>value</code> is null |
* @throws NullPointerException if <code>value</code> is null |
330 |
*/ |
*/ |
331 |
public synchronized boolean contains(Object value) |
public synchronized boolean contains(Object value) |
332 |
{ |
{ |
|
// Check if value is null. |
|
|
if (value == null) |
|
|
throw new NullPointerException(); |
|
333 |
return containsValue(value); |
return containsValue(value); |
334 |
} |
} |
335 |
|
|
336 |
/** |
/** |
337 |
* Returns true if this Hashtable contains a value <code>o</code>, such that |
* Returns true if this Hashtable contains a value <code>o</code>, such that |
338 |
* <code>o.equals(value)</code>. This is the new API for the old |
* <code>o.equals(value)</code>. This is the new API for the old |
339 |
* <code>contains()</code>, except that it is forgiving of null. |
* <code>contains()</code>. |
340 |
* |
* |
341 |
* @param value the value to search for in this Hashtable |
* @param value the value to search for in this Hashtable |
342 |
* @return true if at least one key maps to the value |
* @return true if at least one key maps to the value |
343 |
|
* @throws NullPointerException if <code>value</code> is null |
344 |
* @see #contains(Object) |
* @see #contains(Object) |
345 |
* @see #containsKey(Object) |
* @see #containsKey(Object) |
346 |
* @since 1.2 |
* @since 1.2 |
352 |
HashEntry e = buckets[i]; |
HashEntry e = buckets[i]; |
353 |
while (e != null) |
while (e != null) |
354 |
{ |
{ |
355 |
if (AbstractCollection.equals(value, e.value)) |
if (value.equals(e.value)) |
356 |
return true; |
return true; |
357 |
e = e.next; |
e = e.next; |
358 |
} |
} |
359 |
} |
} |
360 |
|
|
361 |
|
// Must throw on null argument even if the table is empty |
362 |
|
if (value == null) |
363 |
|
throw new NullPointerException(); |
364 |
|
|
365 |
return false; |
return false; |
366 |
} |
} |
367 |
|
|
467 |
* Removes from the table and returns the value which is mapped by the |
* Removes from the table and returns the value which is mapped by the |
468 |
* supplied key. If the key maps to nothing, then the table remains |
* supplied key. If the key maps to nothing, then the table remains |
469 |
* unchanged, and <code>null</code> is returned. |
* unchanged, and <code>null</code> is returned. |
|
* <b>NOTE:</b>Map.remove and Dictionary.remove disagree whether null |
|
|
* is a valid parameter; at the moment, this implementation obeys Map.remove, |
|
|
* and silently ignores null. |
|
470 |
* |
* |
471 |
* @param key the key used to locate the value to remove |
* @param key the key used to locate the value to remove |
472 |
* @return whatever the key mapped to, if present |
* @return whatever the key mapped to, if present |
473 |
*/ |
*/ |
474 |
public synchronized Object remove(Object key) |
public synchronized Object remove(Object key) |
475 |
{ |
{ |
|
if (key == null) |
|
|
return null; |
|
476 |
int idx = hash(key); |
int idx = hash(key); |
477 |
HashEntry e = buckets[idx]; |
HashEntry e = buckets[idx]; |
478 |
HashEntry last = null; |
HashEntry last = null; |
511 |
{ |
{ |
512 |
Map.Entry e = (Map.Entry) itr.next(); |
Map.Entry e = (Map.Entry) itr.next(); |
513 |
// Optimize in case the Entry is one of our own. |
// Optimize in case the Entry is one of our own. |
514 |
if (e instanceof AbstractMap.BasicMapEntry) |
if (e instanceof BasicMapEntry) |
515 |
{ |
{ |
516 |
AbstractMap.BasicMapEntry entry = (AbstractMap.BasicMapEntry) e; |
BasicMapEntry entry = (BasicMapEntry) e; |
517 |
put(entry.key, entry.value); |
put(entry.key, entry.value); |
518 |
} |
} |
519 |
else |
else |
812 |
*/ |
*/ |
813 |
private int hash(Object key) |
private int hash(Object key) |
814 |
{ |
{ |
815 |
// Note: Inline Math.abs here, for less method overhead, and to avoid |
return Math.abs(key.hashCode() % buckets.length); |
|
// a bootstrap dependency, since Math relies on native methods. |
|
|
int hash = key.hashCode() % buckets.length; |
|
|
return hash < 0 ? -hash : hash; |
|
816 |
} |
} |
817 |
|
|
818 |
/** |
/** |
1139 |
return type == VALUES ? e.value : e.key; |
return type == VALUES ? e.value : e.key; |
1140 |
} |
} |
1141 |
} // class Enumerator |
} // class Enumerator |
1142 |
} // class Hashtable |
} |