src/share/classes/com/sun/corba/se/impl/util/IdentityHashtable.java

Mon, 29 Oct 2012 14:10:49 +0100

author
ohrstrom
date
Mon, 29 Oct 2012 14:10:49 +0100
changeset 416
643e7612cf6d
parent 158
91006f157c46
child 748
6845b95cba6b
permissions
-rw-r--r--

8000970: break out auxiliary classes that will prevent multi-core compilation of the JDK.
Reviewed-by: alanb, wetmore

duke@1 1 /*
ohair@158 2 * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
duke@1 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1 4 *
duke@1 5 * This code is free software; you can redistribute it and/or modify it
duke@1 6 * under the terms of the GNU General Public License version 2 only, as
ohair@158 7 * published by the Free Software Foundation. Oracle designates this
duke@1 8 * particular file as subject to the "Classpath" exception as provided
ohair@158 9 * by Oracle in the LICENSE file that accompanied this code.
duke@1 10 *
duke@1 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@1 15 * accompanied this code).
duke@1 16 *
duke@1 17 * You should have received a copy of the GNU General Public License version
duke@1 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@1 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1 20 *
ohair@158 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@158 22 * or visit www.oracle.com if you need additional information or have any
ohair@158 23 * questions.
duke@1 24 */
duke@1 25
duke@1 26 /*
duke@1 27 * Licensed Materials - Property of IBM
duke@1 28 * RMI-IIOP v1.0
duke@1 29 * Copyright IBM Corp. 1998 1999 All Rights Reserved
duke@1 30 *
duke@1 31 */
duke@1 32
duke@1 33 package com.sun.corba.se.impl.util;
duke@1 34
duke@1 35 import java.util.Dictionary;
duke@1 36 import java.util.Enumeration;
duke@1 37 import java.util.NoSuchElementException;
duke@1 38
duke@1 39 /**
duke@1 40 * IdentityHashtable is a modified copy of the 1.1.6 Hashtable class which
duke@1 41 * does not rely on the hashCode() and equals() methods of the key or value;
duke@1 42 * instead, it uses the System.identityHashcode() method and pointer comparison.
duke@1 43 * In addition, all synchronization has been removed.
duke@1 44 */
duke@1 45 public final class IdentityHashtable extends Dictionary {
duke@1 46 /**
duke@1 47 * The hash table data.
duke@1 48 */
duke@1 49 private transient IdentityHashtableEntry table[];
duke@1 50
duke@1 51 /**
duke@1 52 * The total number of entries in the hash table.
duke@1 53 */
duke@1 54 private transient int count;
duke@1 55
duke@1 56 /**
duke@1 57 * Rehashes the table when count exceeds this threshold.
duke@1 58 */
duke@1 59 private int threshold;
duke@1 60
duke@1 61 /**
duke@1 62 * The load factor for the hashtable.
duke@1 63 */
duke@1 64 private float loadFactor;
duke@1 65
duke@1 66 /**
duke@1 67 * Constructs a new, empty hashtable with the specified initial
duke@1 68 * capacity and the specified load factor.
duke@1 69 *
duke@1 70 * @param initialCapacity the initial capacity of the hashtable.
duke@1 71 * @param loadFactor a number between 0.0 and 1.0.
duke@1 72 * @exception IllegalArgumentException if the initial capacity is less
duke@1 73 * than or equal to zero, or if the load factor is less than
duke@1 74 * or equal to zero.
duke@1 75 * @since JDK1.0
duke@1 76 */
duke@1 77 public IdentityHashtable(int initialCapacity, float loadFactor) {
duke@1 78 if ((initialCapacity <= 0) || (loadFactor <= 0.0)) {
duke@1 79 throw new IllegalArgumentException();
duke@1 80 }
duke@1 81 this.loadFactor = loadFactor;
duke@1 82 table = new IdentityHashtableEntry[initialCapacity];
duke@1 83 threshold = (int)(initialCapacity * loadFactor);
duke@1 84 }
duke@1 85
duke@1 86 /**
duke@1 87 * Constructs a new, empty hashtable with the specified initial capacity
duke@1 88 * and default load factor.
duke@1 89 *
duke@1 90 * @param initialCapacity the initial capacity of the hashtable.
duke@1 91 * @since JDK1.0
duke@1 92 */
duke@1 93 public IdentityHashtable(int initialCapacity) {
duke@1 94 this(initialCapacity, 0.75f);
duke@1 95 }
duke@1 96
duke@1 97 /**
duke@1 98 * Constructs a new, empty hashtable with a default capacity and load
duke@1 99 * factor.
duke@1 100 *
duke@1 101 * @since JDK1.0
duke@1 102 */
duke@1 103 public IdentityHashtable() {
duke@1 104 this(101, 0.75f);
duke@1 105 }
duke@1 106
duke@1 107 /**
duke@1 108 * Returns the number of keys in this hashtable.
duke@1 109 *
duke@1 110 * @return the number of keys in this hashtable.
duke@1 111 * @since JDK1.0
duke@1 112 */
duke@1 113 public int size() {
duke@1 114 return count;
duke@1 115 }
duke@1 116
duke@1 117 /**
duke@1 118 * Tests if this hashtable maps no keys to values.
duke@1 119 *
duke@1 120 * @return <code>true</code> if this hashtable maps no keys to values;
duke@1 121 * <code>false</code> otherwise.
duke@1 122 * @since JDK1.0
duke@1 123 */
duke@1 124 public boolean isEmpty() {
duke@1 125 return count == 0;
duke@1 126 }
duke@1 127
duke@1 128 /**
duke@1 129 * Returns an enumeration of the keys in this hashtable.
duke@1 130 *
duke@1 131 * @return an enumeration of the keys in this hashtable.
duke@1 132 * @see java.util.Enumeration
duke@1 133 * @see java.util.Hashtable#elements()
duke@1 134 * @since JDK1.0
duke@1 135 */
duke@1 136 public Enumeration keys() {
duke@1 137 return new IdentityHashtableEnumerator(table, true);
duke@1 138 }
duke@1 139
duke@1 140 /**
duke@1 141 * Returns an enumeration of the values in this hashtable.
duke@1 142 * Use the Enumeration methods on the returned object to fetch the elements
duke@1 143 * sequentially.
duke@1 144 *
duke@1 145 * @return an enumeration of the values in this hashtable.
duke@1 146 * @see java.util.Enumeration
duke@1 147 * @see java.util.Hashtable#keys()
duke@1 148 * @since JDK1.0
duke@1 149 */
duke@1 150 public Enumeration elements() {
duke@1 151 return new IdentityHashtableEnumerator(table, false);
duke@1 152 }
duke@1 153
duke@1 154 /**
duke@1 155 * Tests if some key maps into the specified value in this hashtable.
duke@1 156 * This operation is more expensive than the <code>containsKey</code>
duke@1 157 * method.
duke@1 158 *
duke@1 159 * @param value a value to search for.
duke@1 160 * @return <code>true</code> if some key maps to the
duke@1 161 * <code>value</code> argument in this hashtable;
duke@1 162 * <code>false</code> otherwise.
duke@1 163 * @exception NullPointerException if the value is <code>null</code>.
duke@1 164 * @see java.util.Hashtable#containsKey(java.lang.Object)
duke@1 165 * @since JDK1.0
duke@1 166 */
duke@1 167 public boolean contains(Object value) {
duke@1 168 if (value == null) {
duke@1 169 throw new NullPointerException();
duke@1 170 }
duke@1 171
duke@1 172 IdentityHashtableEntry tab[] = table;
duke@1 173 for (int i = tab.length ; i-- > 0 ;) {
duke@1 174 for (IdentityHashtableEntry e = tab[i] ; e != null ; e = e.next) {
duke@1 175 if (e.value == value) {
duke@1 176 return true;
duke@1 177 }
duke@1 178 }
duke@1 179 }
duke@1 180 return false;
duke@1 181 }
duke@1 182
duke@1 183 /**
duke@1 184 * Tests if the specified object is a key in this hashtable.
duke@1 185 *
duke@1 186 * @param key possible key.
duke@1 187 * @return <code>true</code> if the specified object is a key in this
duke@1 188 * hashtable; <code>false</code> otherwise.
duke@1 189 * @see java.util.Hashtable#contains(java.lang.Object)
duke@1 190 * @since JDK1.0
duke@1 191 */
duke@1 192 public boolean containsKey(Object key) {
duke@1 193 IdentityHashtableEntry tab[] = table;
duke@1 194 int hash = System.identityHashCode(key);
duke@1 195 int index = (hash & 0x7FFFFFFF) % tab.length;
duke@1 196 for (IdentityHashtableEntry e = tab[index] ; e != null ; e = e.next) {
duke@1 197 if ((e.hash == hash) && e.key == key) {
duke@1 198 return true;
duke@1 199 }
duke@1 200 }
duke@1 201 return false;
duke@1 202 }
duke@1 203
duke@1 204 /**
duke@1 205 * Returns the value to which the specified key is mapped in this hashtable.
duke@1 206 *
duke@1 207 * @param key a key in the hashtable.
duke@1 208 * @return the value to which the key is mapped in this hashtable;
duke@1 209 * <code>null</code> if the key is not mapped to any value in
duke@1 210 * this hashtable.
duke@1 211 * @see java.util.Hashtable#put(java.lang.Object, java.lang.Object)
duke@1 212 * @since JDK1.0
duke@1 213 */
duke@1 214 public Object get(Object key) {
duke@1 215 IdentityHashtableEntry tab[] = table;
duke@1 216 int hash = System.identityHashCode(key);
duke@1 217 int index = (hash & 0x7FFFFFFF) % tab.length;
duke@1 218 for (IdentityHashtableEntry e = tab[index] ; e != null ; e = e.next) {
duke@1 219 if ((e.hash == hash) && e.key == key) {
duke@1 220 return e.value;
duke@1 221 }
duke@1 222 }
duke@1 223 return null;
duke@1 224 }
duke@1 225
duke@1 226 /**
duke@1 227 * Rehashes the contents of the hashtable into a hashtable with a
duke@1 228 * larger capacity. This method is called automatically when the
duke@1 229 * number of keys in the hashtable exceeds this hashtable's capacity
duke@1 230 * and load factor.
duke@1 231 *
duke@1 232 * @since JDK1.0
duke@1 233 */
duke@1 234 protected void rehash() {
duke@1 235 int oldCapacity = table.length;
duke@1 236 IdentityHashtableEntry oldTable[] = table;
duke@1 237
duke@1 238 int newCapacity = oldCapacity * 2 + 1;
duke@1 239 IdentityHashtableEntry newTable[] = new IdentityHashtableEntry[newCapacity];
duke@1 240
duke@1 241 threshold = (int)(newCapacity * loadFactor);
duke@1 242 table = newTable;
duke@1 243
duke@1 244 //System.out.println("rehash old=" + oldCapacity + ", new=" + newCapacity + ", thresh=" + threshold + ", count=" + count);
duke@1 245
duke@1 246 for (int i = oldCapacity ; i-- > 0 ;) {
duke@1 247 for (IdentityHashtableEntry old = oldTable[i] ; old != null ; ) {
duke@1 248 IdentityHashtableEntry e = old;
duke@1 249 old = old.next;
duke@1 250
duke@1 251 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
duke@1 252 e.next = newTable[index];
duke@1 253 newTable[index] = e;
duke@1 254 }
duke@1 255 }
duke@1 256 }
duke@1 257
duke@1 258 /**
duke@1 259 * Maps the specified <code>key</code> to the specified
duke@1 260 * <code>value</code> in this hashtable. Neither the key nor the
duke@1 261 * value can be <code>null</code>.
duke@1 262 * <p>
duke@1 263 * The value can be retrieved by calling the <code>get</code> method
duke@1 264 * with a key that is equal to the original key.
duke@1 265 *
duke@1 266 * @param key the hashtable key.
duke@1 267 * @param value the value.
duke@1 268 * @return the previous value of the specified key in this hashtable,
duke@1 269 * or <code>null</code> if it did not have one.
duke@1 270 * @exception NullPointerException if the key or value is
duke@1 271 * <code>null</code>.
duke@1 272 * @see java.util.Hashtable#get(java.lang.Object)
duke@1 273 * @since JDK1.0
duke@1 274 */
duke@1 275 public Object put(Object key, Object value) {
duke@1 276 // Make sure the value is not null
duke@1 277 if (value == null) {
duke@1 278 throw new NullPointerException();
duke@1 279 }
duke@1 280
duke@1 281 // Makes sure the key is not already in the hashtable.
duke@1 282 IdentityHashtableEntry tab[] = table;
duke@1 283 int hash = System.identityHashCode(key);
duke@1 284 int index = (hash & 0x7FFFFFFF) % tab.length;
duke@1 285 for (IdentityHashtableEntry e = tab[index] ; e != null ; e = e.next) {
duke@1 286 if ((e.hash == hash) && e.key == key) {
duke@1 287 Object old = e.value;
duke@1 288 e.value = value;
duke@1 289 return old;
duke@1 290 }
duke@1 291 }
duke@1 292
duke@1 293 if (count >= threshold) {
duke@1 294 // Rehash the table if the threshold is exceeded
duke@1 295 rehash();
duke@1 296 return put(key, value);
duke@1 297 }
duke@1 298
duke@1 299 // Creates the new entry.
duke@1 300 IdentityHashtableEntry e = new IdentityHashtableEntry();
duke@1 301 e.hash = hash;
duke@1 302 e.key = key;
duke@1 303 e.value = value;
duke@1 304 e.next = tab[index];
duke@1 305 tab[index] = e;
duke@1 306 count++;
duke@1 307 return null;
duke@1 308 }
duke@1 309
duke@1 310 /**
duke@1 311 * Removes the key (and its corresponding value) from this
duke@1 312 * hashtable. This method does nothing if the key is not in the hashtable.
duke@1 313 *
duke@1 314 * @param key the key that needs to be removed.
duke@1 315 * @return the value to which the key had been mapped in this hashtable,
duke@1 316 * or <code>null</code> if the key did not have a mapping.
duke@1 317 * @since JDK1.0
duke@1 318 */
duke@1 319 public Object remove(Object key) {
duke@1 320 IdentityHashtableEntry tab[] = table;
duke@1 321 int hash = System.identityHashCode(key);
duke@1 322 int index = (hash & 0x7FFFFFFF) % tab.length;
duke@1 323 for (IdentityHashtableEntry e = tab[index], prev = null ; e != null ; prev = e, e = e.next) {
duke@1 324 if ((e.hash == hash) && e.key == key) {
duke@1 325 if (prev != null) {
duke@1 326 prev.next = e.next;
duke@1 327 } else {
duke@1 328 tab[index] = e.next;
duke@1 329 }
duke@1 330 count--;
duke@1 331 return e.value;
duke@1 332 }
duke@1 333 }
duke@1 334 return null;
duke@1 335 }
duke@1 336
duke@1 337 /**
duke@1 338 * Clears this hashtable so that it contains no keys.
duke@1 339 *
duke@1 340 * @since JDK1.0
duke@1 341 */
duke@1 342 public void clear() {
duke@1 343 IdentityHashtableEntry tab[] = table;
duke@1 344 for (int index = tab.length; --index >= 0; )
duke@1 345 tab[index] = null;
duke@1 346 count = 0;
duke@1 347 }
duke@1 348
duke@1 349 /**
duke@1 350 * Returns a rather long string representation of this hashtable.
duke@1 351 *
duke@1 352 * @return a string representation of this hashtable.
duke@1 353 * @since JDK1.0
duke@1 354 */
duke@1 355 public String toString() {
duke@1 356 int max = size() - 1;
duke@1 357 StringBuffer buf = new StringBuffer();
duke@1 358 Enumeration k = keys();
duke@1 359 Enumeration e = elements();
duke@1 360 buf.append("{");
duke@1 361
duke@1 362 for (int i = 0; i <= max; i++) {
duke@1 363 String s1 = k.nextElement().toString();
duke@1 364 String s2 = e.nextElement().toString();
duke@1 365 buf.append(s1 + "=" + s2);
duke@1 366 if (i < max) {
duke@1 367 buf.append(", ");
duke@1 368 }
duke@1 369 }
duke@1 370 buf.append("}");
duke@1 371 return buf.toString();
duke@1 372 }
duke@1 373 }

mercurial