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

Thu, 12 Oct 2017 19:44:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:44:07 +0800
changeset 760
e530533619ec
parent 637
9c07ef4934dd
permissions
-rw-r--r--

merge

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

mercurial