src/share/jaxws_classes/com/sun/xml/internal/dtdparser/SimpleHashtable.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 397
b99d7e355d4b
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.xml.internal.dtdparser;
aoqi@0 27
aoqi@0 28 import java.util.Enumeration;
aoqi@0 29
aoqi@0 30
aoqi@0 31 // This could be replaced by Collections class unless we want
aoqi@0 32 // to be able to run on JDK 1.1
aoqi@0 33
aoqi@0 34
aoqi@0 35 /**
aoqi@0 36 * This class implements a special purpose hashtable. It works like a
aoqi@0 37 * normal <code>java.util.Hashtable</code> except that: <OL>
aoqi@0 38 * <p/>
aoqi@0 39 * <LI> Keys to "get" are strings which are known to be interned,
aoqi@0 40 * so that "==" is used instead of "String.equals". (Interning
aoqi@0 41 * could be document-relative instead of global.)
aoqi@0 42 * <p/>
aoqi@0 43 * <LI> It's not synchronized, since it's to be used only by
aoqi@0 44 * one thread at a time.
aoqi@0 45 * <p/>
aoqi@0 46 * <LI> The keys () enumerator allocates no memory, with live
aoqi@0 47 * updates to the data disallowed.
aoqi@0 48 * <p/>
aoqi@0 49 * <LI> It's got fewer bells and whistles: fixed threshold and
aoqi@0 50 * load factor, no JDK 1.2 collection support, only keys can be
aoqi@0 51 * enumerated, things can't be removed, simpler inheritance; more.
aoqi@0 52 * <p/>
aoqi@0 53 * </OL>
aoqi@0 54 * <p/>
aoqi@0 55 * <P> The overall result is that it's less expensive to use these in
aoqi@0 56 * performance-critical locations, in terms both of CPU and memory,
aoqi@0 57 * than <code>java.util.Hashtable</code> instances. In this package
aoqi@0 58 * it makes a significant difference when normalizing attributes,
aoqi@0 59 * which is done for each start-element construct.
aoqi@0 60 *
aoqi@0 61 * @version $Revision: 1.2 $
aoqi@0 62 */
aoqi@0 63 final class SimpleHashtable implements Enumeration {
aoqi@0 64 // entries ...
aoqi@0 65 private Entry table[];
aoqi@0 66
aoqi@0 67 // currently enumerated key
aoqi@0 68 private Entry current = null;
aoqi@0 69 private int currentBucket = 0;
aoqi@0 70
aoqi@0 71 private int count;
aoqi@0 72 private int threshold;
aoqi@0 73
aoqi@0 74 private static final float loadFactor = 0.75f;
aoqi@0 75
aoqi@0 76
aoqi@0 77 /**
aoqi@0 78 * Constructs a new, empty hashtable with the specified initial
aoqi@0 79 * capacity.
aoqi@0 80 *
aoqi@0 81 * @param initialCapacity the initial capacity of the hashtable.
aoqi@0 82 */
aoqi@0 83 public SimpleHashtable(int initialCapacity) {
aoqi@0 84 if (initialCapacity < 0)
aoqi@0 85 throw new IllegalArgumentException("Illegal Capacity: " +
aoqi@0 86 initialCapacity);
aoqi@0 87 if (initialCapacity == 0)
aoqi@0 88 initialCapacity = 1;
aoqi@0 89 table = new Entry[initialCapacity];
aoqi@0 90 threshold = (int) (initialCapacity * loadFactor);
aoqi@0 91 }
aoqi@0 92
aoqi@0 93 /**
aoqi@0 94 * Constructs a new, empty hashtable with a default capacity.
aoqi@0 95 */
aoqi@0 96 public SimpleHashtable() {
aoqi@0 97 this(11);
aoqi@0 98 }
aoqi@0 99
aoqi@0 100 /**
aoqi@0 101 */
aoqi@0 102 public void clear() {
aoqi@0 103 count = 0;
aoqi@0 104 currentBucket = 0;
aoqi@0 105 current = null;
aoqi@0 106 for (int i = 0; i < table.length; i++)
aoqi@0 107 table[i] = null;
aoqi@0 108 }
aoqi@0 109
aoqi@0 110 /**
aoqi@0 111 * Returns the number of keys in this hashtable.
aoqi@0 112 *
aoqi@0 113 * @return the number of keys in this hashtable.
aoqi@0 114 */
aoqi@0 115 public int size() {
aoqi@0 116 return count;
aoqi@0 117 }
aoqi@0 118
aoqi@0 119 /**
aoqi@0 120 * Returns an enumeration of the keys in this hashtable.
aoqi@0 121 *
aoqi@0 122 * @return an enumeration of the keys in this hashtable.
aoqi@0 123 * @see Enumeration
aoqi@0 124 */
aoqi@0 125 public Enumeration keys() {
aoqi@0 126 currentBucket = 0;
aoqi@0 127 current = null;
aoqi@0 128 return this;
aoqi@0 129 }
aoqi@0 130
aoqi@0 131 /**
aoqi@0 132 * Used to view this as an enumeration; returns true if there
aoqi@0 133 * are more keys to be enumerated.
aoqi@0 134 */
aoqi@0 135 public boolean hasMoreElements() {
aoqi@0 136 if (current != null)
aoqi@0 137 return true;
aoqi@0 138 while (currentBucket < table.length) {
aoqi@0 139 current = table[currentBucket++];
aoqi@0 140 if (current != null)
aoqi@0 141 return true;
aoqi@0 142 }
aoqi@0 143 return false;
aoqi@0 144 }
aoqi@0 145
aoqi@0 146 /**
aoqi@0 147 * Used to view this as an enumeration; returns the next key
aoqi@0 148 * in the enumeration.
aoqi@0 149 */
aoqi@0 150 public Object nextElement() {
aoqi@0 151 Object retval;
aoqi@0 152
aoqi@0 153 if (current == null)
aoqi@0 154 throw new IllegalStateException();
aoqi@0 155 retval = current.key;
aoqi@0 156 current = current.next;
aoqi@0 157 return retval;
aoqi@0 158 }
aoqi@0 159
aoqi@0 160
aoqi@0 161 /**
aoqi@0 162 * Returns the value to which the specified key is mapped in this hashtable.
aoqi@0 163 */
aoqi@0 164 public Object get(String key) {
aoqi@0 165 Entry tab[] = table;
aoqi@0 166 int hash = key.hashCode();
aoqi@0 167 int index = (hash & 0x7FFFFFFF) % tab.length;
aoqi@0 168 for (Entry e = tab[index]; e != null; e = e.next) {
aoqi@0 169 if ((e.hash == hash) && (e.key == key))
aoqi@0 170 return e.value;
aoqi@0 171 }
aoqi@0 172 return null;
aoqi@0 173 }
aoqi@0 174
aoqi@0 175 /**
aoqi@0 176 * Returns the value to which the specified key is mapped in this
aoqi@0 177 * hashtable ... the key isn't necessarily interned, though.
aoqi@0 178 */
aoqi@0 179 public Object getNonInterned(String key) {
aoqi@0 180 Entry tab[] = table;
aoqi@0 181 int hash = key.hashCode();
aoqi@0 182 int index = (hash & 0x7FFFFFFF) % tab.length;
aoqi@0 183 for (Entry e = tab[index]; e != null; e = e.next) {
aoqi@0 184 if ((e.hash == hash) && e.key.equals(key))
aoqi@0 185 return e.value;
aoqi@0 186 }
aoqi@0 187 return null;
aoqi@0 188 }
aoqi@0 189
aoqi@0 190 /**
aoqi@0 191 * Increases the capacity of and internally reorganizes this
aoqi@0 192 * hashtable, in order to accommodate and access its entries more
aoqi@0 193 * efficiently. This method is called automatically when the
aoqi@0 194 * number of keys in the hashtable exceeds this hashtable's capacity
aoqi@0 195 * and load factor.
aoqi@0 196 */
aoqi@0 197 private void rehash() {
aoqi@0 198 int oldCapacity = table.length;
aoqi@0 199 Entry oldMap[] = table;
aoqi@0 200
aoqi@0 201 int newCapacity = oldCapacity * 2 + 1;
aoqi@0 202 Entry newMap[] = new Entry[newCapacity];
aoqi@0 203
aoqi@0 204 threshold = (int) (newCapacity * loadFactor);
aoqi@0 205 table = newMap;
aoqi@0 206
aoqi@0 207 /*
aoqi@0 208 System.out.println("rehash old=" + oldCapacity
aoqi@0 209 + ", new=" + newCapacity
aoqi@0 210 + ", thresh=" + threshold
aoqi@0 211 + ", count=" + count);
aoqi@0 212 */
aoqi@0 213
aoqi@0 214 for (int i = oldCapacity; i-- > 0;) {
aoqi@0 215 for (Entry old = oldMap[i]; old != null;) {
aoqi@0 216 Entry e = old;
aoqi@0 217 old = old.next;
aoqi@0 218
aoqi@0 219 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
aoqi@0 220 e.next = newMap[index];
aoqi@0 221 newMap[index] = e;
aoqi@0 222 }
aoqi@0 223 }
aoqi@0 224 }
aoqi@0 225
aoqi@0 226 /**
aoqi@0 227 * Maps the specified <code>key</code> to the specified
aoqi@0 228 * <code>value</code> in this hashtable. Neither the key nor the
aoqi@0 229 * value can be <code>null</code>.
aoqi@0 230 * <p/>
aoqi@0 231 * <P>The value can be retrieved by calling the <code>get</code> method
aoqi@0 232 * with a key that is equal to the original key.
aoqi@0 233 */
aoqi@0 234 public Object put(Object key, Object value) {
aoqi@0 235 // Make sure the value is not null
aoqi@0 236 if (value == null) {
aoqi@0 237 throw new NullPointerException();
aoqi@0 238 }
aoqi@0 239
aoqi@0 240 // Makes sure the key is not already in the hashtable.
aoqi@0 241 Entry tab[] = table;
aoqi@0 242 int hash = key.hashCode();
aoqi@0 243 int index = (hash & 0x7FFFFFFF) % tab.length;
aoqi@0 244 for (Entry e = tab[index]; e != null; e = e.next) {
aoqi@0 245 // if ((e.hash == hash) && e.key.equals(key)) {
aoqi@0 246 if ((e.hash == hash) && (e.key == key)) {
aoqi@0 247 Object old = e.value;
aoqi@0 248 e.value = value;
aoqi@0 249 return old;
aoqi@0 250 }
aoqi@0 251 }
aoqi@0 252
aoqi@0 253 if (count >= threshold) {
aoqi@0 254 // Rehash the table if the threshold is exceeded
aoqi@0 255 rehash();
aoqi@0 256
aoqi@0 257 tab = table;
aoqi@0 258 index = (hash & 0x7FFFFFFF) % tab.length;
aoqi@0 259 }
aoqi@0 260
aoqi@0 261 // Creates the new entry.
aoqi@0 262 Entry e = new Entry(hash, key, value, tab[index]);
aoqi@0 263 tab[index] = e;
aoqi@0 264 count++;
aoqi@0 265 return null;
aoqi@0 266 }
aoqi@0 267
aoqi@0 268
aoqi@0 269 /**
aoqi@0 270 * Hashtable collision list.
aoqi@0 271 */
aoqi@0 272 private static class Entry {
aoqi@0 273 int hash;
aoqi@0 274 Object key;
aoqi@0 275 Object value;
aoqi@0 276 Entry next;
aoqi@0 277
aoqi@0 278 protected Entry(int hash, Object key, Object value, Entry next) {
aoqi@0 279 this.hash = hash;
aoqi@0 280 this.key = key;
aoqi@0 281 this.value = value;
aoqi@0 282 this.next = next;
aoqi@0 283 }
aoqi@0 284 }
aoqi@0 285 }

mercurial