Source Code Cross Referenced for Hashtable.java in  » 6.0-JDK-Core » Collections-Jar-Zip-Logging-regex » java » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » Collections Jar Zip Logging regex » java.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1994-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package java.util;
0027
0028        import java.io.*;
0029
0030        /**
0031         * This class implements a hashtable, which maps keys to values. Any
0032         * non-<code>null</code> object can be used as a key or as a value. <p>
0033         *
0034         * To successfully store and retrieve objects from a hashtable, the
0035         * objects used as keys must implement the <code>hashCode</code>
0036         * method and the <code>equals</code> method. <p>
0037         *
0038         * An instance of <code>Hashtable</code> has two parameters that affect its
0039         * performance: <i>initial capacity</i> and <i>load factor</i>.  The
0040         * <i>capacity</i> is the number of <i>buckets</i> in the hash table, and the
0041         * <i>initial capacity</i> is simply the capacity at the time the hash table
0042         * is created.  Note that the hash table is <i>open</i>: in the case of a "hash
0043         * collision", a single bucket stores multiple entries, which must be searched
0044         * sequentially.  The <i>load factor</i> is a measure of how full the hash
0045         * table is allowed to get before its capacity is automatically increased.
0046         * The initial capacity and load factor parameters are merely hints to
0047         * the implementation.  The exact details as to when and whether the rehash
0048         * method is invoked are implementation-dependent.<p>
0049         *
0050         * Generally, the default load factor (.75) offers a good tradeoff between
0051         * time and space costs.  Higher values decrease the space overhead but
0052         * increase the time cost to look up an entry (which is reflected in most
0053         * <tt>Hashtable</tt> operations, including <tt>get</tt> and <tt>put</tt>).<p>
0054         *
0055         * The initial capacity controls a tradeoff between wasted space and the
0056         * need for <code>rehash</code> operations, which are time-consuming.
0057         * No <code>rehash</code> operations will <i>ever</i> occur if the initial
0058         * capacity is greater than the maximum number of entries the
0059         * <tt>Hashtable</tt> will contain divided by its load factor.  However,
0060         * setting the initial capacity too high can waste space.<p>
0061         *
0062         * If many entries are to be made into a <code>Hashtable</code>,
0063         * creating it with a sufficiently large capacity may allow the
0064         * entries to be inserted more efficiently than letting it perform
0065         * automatic rehashing as needed to grow the table. <p>
0066         *
0067         * This example creates a hashtable of numbers. It uses the names of
0068         * the numbers as keys:
0069         * <pre>   {@code
0070         *   Hashtable<String, Integer> numbers
0071         *     = new Hashtable<String, Integer>();
0072         *   numbers.put("one", 1);
0073         *   numbers.put("two", 2);
0074         *   numbers.put("three", 3);}</pre>
0075         *
0076         * <p>To retrieve a number, use the following code:
0077         * <pre>   {@code
0078         *   Integer n = numbers.get("two");
0079         *   if (n != null) {
0080         *     System.out.println("two = " + n);
0081         *   }}</pre>
0082         *
0083         * <p>The iterators returned by the <tt>iterator</tt> method of the collections
0084         * returned by all of this class's "collection view methods" are
0085         * <em>fail-fast</em>: if the Hashtable is structurally modified at any time
0086         * after the iterator is created, in any way except through the iterator's own
0087         * <tt>remove</tt> method, the iterator will throw a {@link
0088         * ConcurrentModificationException}.  Thus, in the face of concurrent
0089         * modification, the iterator fails quickly and cleanly, rather than risking
0090         * arbitrary, non-deterministic behavior at an undetermined time in the future.
0091         * The Enumerations returned by Hashtable's keys and elements methods are
0092         * <em>not</em> fail-fast.
0093         *
0094         * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
0095         * as it is, generally speaking, impossible to make any hard guarantees in the
0096         * presence of unsynchronized concurrent modification.  Fail-fast iterators
0097         * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
0098         * Therefore, it would be wrong to write a program that depended on this
0099         * exception for its correctness: <i>the fail-fast behavior of iterators
0100         * should be used only to detect bugs.</i>
0101         *
0102         * <p>As of the Java 2 platform v1.2, this class was retrofitted to
0103         * implement the {@link Map} interface, making it a member of the
0104         * <a href="{@docRoot}/../technotes/guides/collections/index.html"> Java
0105         * Collections Framework</a>.  Unlike the new collection
0106         * implementations, {@code Hashtable} is synchronized.
0107         *
0108         * @author  Arthur van Hoff
0109         * @author  Josh Bloch
0110         * @author  Neal Gafter
0111         * @version 1.123, 07/08/07
0112         * @see     Object#equals(java.lang.Object)
0113         * @see     Object#hashCode()
0114         * @see     Hashtable#rehash()
0115         * @see     Collection
0116         * @see	    Map
0117         * @see	    HashMap
0118         * @see	    TreeMap
0119         * @since JDK1.0
0120         */
0121        public class Hashtable<K, V> extends Dictionary<K, V> implements 
0122                Map<K, V>, Cloneable, java.io.Serializable {
0123
0124            /**
0125             * The hash table data.
0126             */
0127            private transient Entry[] table;
0128
0129            /**
0130             * The total number of entries in the hash table.
0131             */
0132            private transient int count;
0133
0134            /**
0135             * The table is rehashed when its size exceeds this threshold.  (The
0136             * value of this field is (int)(capacity * loadFactor).)
0137             *
0138             * @serial
0139             */
0140            private int threshold;
0141
0142            /**
0143             * The load factor for the hashtable.
0144             *
0145             * @serial
0146             */
0147            private float loadFactor;
0148
0149            /**
0150             * The number of times this Hashtable has been structurally modified
0151             * Structural modifications are those that change the number of entries in
0152             * the Hashtable or otherwise modify its internal structure (e.g.,
0153             * rehash).  This field is used to make iterators on Collection-views of
0154             * the Hashtable fail-fast.  (See ConcurrentModificationException).
0155             */
0156            private transient int modCount = 0;
0157
0158            /** use serialVersionUID from JDK 1.0.2 for interoperability */
0159            private static final long serialVersionUID = 1421746759512286392L;
0160
0161            /**
0162             * Constructs a new, empty hashtable with the specified initial
0163             * capacity and the specified load factor.
0164             *
0165             * @param      initialCapacity   the initial capacity of the hashtable.
0166             * @param      loadFactor        the load factor of the hashtable.
0167             * @exception  IllegalArgumentException  if the initial capacity is less
0168             *             than zero, or if the load factor is nonpositive.
0169             */
0170            public Hashtable(int initialCapacity, float loadFactor) {
0171                if (initialCapacity < 0)
0172                    throw new IllegalArgumentException("Illegal Capacity: "
0173                            + initialCapacity);
0174                if (loadFactor <= 0 || Float.isNaN(loadFactor))
0175                    throw new IllegalArgumentException("Illegal Load: "
0176                            + loadFactor);
0177
0178                if (initialCapacity == 0)
0179                    initialCapacity = 1;
0180                this .loadFactor = loadFactor;
0181                table = new Entry[initialCapacity];
0182                threshold = (int) (initialCapacity * loadFactor);
0183            }
0184
0185            /**
0186             * Constructs a new, empty hashtable with the specified initial capacity
0187             * and default load factor (0.75).
0188             *
0189             * @param     initialCapacity   the initial capacity of the hashtable.
0190             * @exception IllegalArgumentException if the initial capacity is less
0191             *              than zero.
0192             */
0193            public Hashtable(int initialCapacity) {
0194                this (initialCapacity, 0.75f);
0195            }
0196
0197            /**
0198             * Constructs a new, empty hashtable with a default initial capacity (11)
0199             * and load factor (0.75).
0200             */
0201            public Hashtable() {
0202                this (11, 0.75f);
0203            }
0204
0205            /**
0206             * Constructs a new hashtable with the same mappings as the given
0207             * Map.  The hashtable is created with an initial capacity sufficient to
0208             * hold the mappings in the given Map and a default load factor (0.75).
0209             *
0210             * @param t the map whose mappings are to be placed in this map.
0211             * @throws NullPointerException if the specified map is null.
0212             * @since   1.2
0213             */
0214            public Hashtable(Map<? extends K, ? extends V> t) {
0215                this (Math.max(2 * t.size(), 11), 0.75f);
0216                putAll(t);
0217            }
0218
0219            /**
0220             * Returns the number of keys in this hashtable.
0221             *
0222             * @return  the number of keys in this hashtable.
0223             */
0224            public synchronized int size() {
0225                return count;
0226            }
0227
0228            /**
0229             * Tests if this hashtable maps no keys to values.
0230             *
0231             * @return  <code>true</code> if this hashtable maps no keys to values;
0232             *          <code>false</code> otherwise.
0233             */
0234            public synchronized boolean isEmpty() {
0235                return count == 0;
0236            }
0237
0238            /**
0239             * Returns an enumeration of the keys in this hashtable.
0240             *
0241             * @return  an enumeration of the keys in this hashtable.
0242             * @see     Enumeration
0243             * @see     #elements()
0244             * @see	#keySet()
0245             * @see	Map
0246             */
0247            public synchronized Enumeration<K> keys() {
0248                return this .<K> getEnumeration(KEYS);
0249            }
0250
0251            /**
0252             * Returns an enumeration of the values in this hashtable.
0253             * Use the Enumeration methods on the returned object to fetch the elements
0254             * sequentially.
0255             *
0256             * @return  an enumeration of the values in this hashtable.
0257             * @see     java.util.Enumeration
0258             * @see     #keys()
0259             * @see	#values()
0260             * @see	Map
0261             */
0262            public synchronized Enumeration<V> elements() {
0263                return this .<V> getEnumeration(VALUES);
0264            }
0265
0266            /**
0267             * Tests if some key maps into the specified value in this hashtable.
0268             * This operation is more expensive than the {@link #containsKey
0269             * containsKey} method.
0270             *
0271             * <p>Note that this method is identical in functionality to
0272             * {@link #containsValue containsValue}, (which is part of the
0273             * {@link Map} interface in the collections framework).
0274             *
0275             * @param      value   a value to search for
0276             * @return     <code>true</code> if and only if some key maps to the
0277             *             <code>value</code> argument in this hashtable as
0278             *             determined by the <tt>equals</tt> method;
0279             *             <code>false</code> otherwise.
0280             * @exception  NullPointerException  if the value is <code>null</code>
0281             */
0282            public synchronized boolean contains(Object value) {
0283                if (value == null) {
0284                    throw new NullPointerException();
0285                }
0286
0287                Entry tab[] = table;
0288                for (int i = tab.length; i-- > 0;) {
0289                    for (Entry<K, V> e = tab[i]; e != null; e = e.next) {
0290                        if (e.value.equals(value)) {
0291                            return true;
0292                        }
0293                    }
0294                }
0295                return false;
0296            }
0297
0298            /**
0299             * Returns true if this hashtable maps one or more keys to this value.
0300             *
0301             * <p>Note that this method is identical in functionality to {@link
0302             * #contains contains} (which predates the {@link Map} interface).
0303             *
0304             * @param value value whose presence in this hashtable is to be tested
0305             * @return <tt>true</tt> if this map maps one or more keys to the
0306             *         specified value
0307             * @throws NullPointerException  if the value is <code>null</code>
0308             * @since 1.2
0309             */
0310            public boolean containsValue(Object value) {
0311                return contains(value);
0312            }
0313
0314            /**
0315             * Tests if the specified object is a key in this hashtable.
0316             *
0317             * @param   key   possible key
0318             * @return  <code>true</code> if and only if the specified object
0319             *          is a key in this hashtable, as determined by the
0320             *          <tt>equals</tt> method; <code>false</code> otherwise.
0321             * @throws  NullPointerException  if the key is <code>null</code>
0322             * @see     #contains(Object)
0323             */
0324            public synchronized boolean containsKey(Object key) {
0325                Entry tab[] = table;
0326                int hash = key.hashCode();
0327                int index = (hash & 0x7FFFFFFF) % tab.length;
0328                for (Entry<K, V> e = tab[index]; e != null; e = e.next) {
0329                    if ((e.hash == hash) && e.key.equals(key)) {
0330                        return true;
0331                    }
0332                }
0333                return false;
0334            }
0335
0336            /**
0337             * Returns the value to which the specified key is mapped,
0338             * or {@code null} if this map contains no mapping for the key.
0339             *
0340             * <p>More formally, if this map contains a mapping from a key
0341             * {@code k} to a value {@code v} such that {@code (key.equals(k))},
0342             * then this method returns {@code v}; otherwise it returns
0343             * {@code null}.  (There can be at most one such mapping.)
0344             *
0345             * @param key the key whose associated value is to be returned
0346             * @return the value to which the specified key is mapped, or
0347             *         {@code null} if this map contains no mapping for the key
0348             * @throws NullPointerException if the specified key is null
0349             * @see     #put(Object, Object)
0350             */
0351            public synchronized V get(Object key) {
0352                Entry tab[] = table;
0353                int hash = key.hashCode();
0354                int index = (hash & 0x7FFFFFFF) % tab.length;
0355                for (Entry<K, V> e = tab[index]; e != null; e = e.next) {
0356                    if ((e.hash == hash) && e.key.equals(key)) {
0357                        return e.value;
0358                    }
0359                }
0360                return null;
0361            }
0362
0363            /**
0364             * Increases the capacity of and internally reorganizes this
0365             * hashtable, in order to accommodate and access its entries more
0366             * efficiently.  This method is called automatically when the
0367             * number of keys in the hashtable exceeds this hashtable's capacity
0368             * and load factor.
0369             */
0370            protected void rehash() {
0371                int oldCapacity = table.length;
0372                Entry[] oldMap = table;
0373
0374                int newCapacity = oldCapacity * 2 + 1;
0375                Entry[] newMap = new Entry[newCapacity];
0376
0377                modCount++;
0378                threshold = (int) (newCapacity * loadFactor);
0379                table = newMap;
0380
0381                for (int i = oldCapacity; i-- > 0;) {
0382                    for (Entry<K, V> old = oldMap[i]; old != null;) {
0383                        Entry<K, V> e = old;
0384                        old = old.next;
0385
0386                        int index = (e.hash & 0x7FFFFFFF) % newCapacity;
0387                        e.next = newMap[index];
0388                        newMap[index] = e;
0389                    }
0390                }
0391            }
0392
0393            /**
0394             * Maps the specified <code>key</code> to the specified
0395             * <code>value</code> in this hashtable. Neither the key nor the
0396             * value can be <code>null</code>. <p>
0397             *
0398             * The value can be retrieved by calling the <code>get</code> method
0399             * with a key that is equal to the original key.
0400             *
0401             * @param      key     the hashtable key
0402             * @param      value   the value
0403             * @return     the previous value of the specified key in this hashtable,
0404             *             or <code>null</code> if it did not have one
0405             * @exception  NullPointerException  if the key or value is
0406             *               <code>null</code>
0407             * @see     Object#equals(Object)
0408             * @see     #get(Object)
0409             */
0410            public synchronized V put(K key, V value) {
0411                // Make sure the value is not null
0412                if (value == null) {
0413                    throw new NullPointerException();
0414                }
0415
0416                // Makes sure the key is not already in the hashtable.
0417                Entry tab[] = table;
0418                int hash = key.hashCode();
0419                int index = (hash & 0x7FFFFFFF) % tab.length;
0420                for (Entry<K, V> e = tab[index]; e != null; e = e.next) {
0421                    if ((e.hash == hash) && e.key.equals(key)) {
0422                        V old = e.value;
0423                        e.value = value;
0424                        return old;
0425                    }
0426                }
0427
0428                modCount++;
0429                if (count >= threshold) {
0430                    // Rehash the table if the threshold is exceeded
0431                    rehash();
0432
0433                    tab = table;
0434                    index = (hash & 0x7FFFFFFF) % tab.length;
0435                }
0436
0437                // Creates the new entry.
0438                Entry<K, V> e = tab[index];
0439                tab[index] = new Entry<K, V>(hash, key, value, e);
0440                count++;
0441                return null;
0442            }
0443
0444            /**
0445             * Removes the key (and its corresponding value) from this
0446             * hashtable. This method does nothing if the key is not in the hashtable.
0447             *
0448             * @param   key   the key that needs to be removed
0449             * @return  the value to which the key had been mapped in this hashtable,
0450             *          or <code>null</code> if the key did not have a mapping
0451             * @throws  NullPointerException  if the key is <code>null</code>
0452             */
0453            public synchronized V remove(Object key) {
0454                Entry tab[] = table;
0455                int hash = key.hashCode();
0456                int index = (hash & 0x7FFFFFFF) % tab.length;
0457                for (Entry<K, V> e = tab[index], prev = null; e != null; prev = e, e = e.next) {
0458                    if ((e.hash == hash) && e.key.equals(key)) {
0459                        modCount++;
0460                        if (prev != null) {
0461                            prev.next = e.next;
0462                        } else {
0463                            tab[index] = e.next;
0464                        }
0465                        count--;
0466                        V oldValue = e.value;
0467                        e.value = null;
0468                        return oldValue;
0469                    }
0470                }
0471                return null;
0472            }
0473
0474            /**
0475             * Copies all of the mappings from the specified map to this hashtable.
0476             * These mappings will replace any mappings that this hashtable had for any
0477             * of the keys currently in the specified map.
0478             *
0479             * @param t mappings to be stored in this map
0480             * @throws NullPointerException if the specified map is null
0481             * @since 1.2
0482             */
0483            public synchronized void putAll(Map<? extends K, ? extends V> t) {
0484                for (Map.Entry<? extends K, ? extends V> e : t.entrySet())
0485                    put(e.getKey(), e.getValue());
0486            }
0487
0488            /**
0489             * Clears this hashtable so that it contains no keys.
0490             */
0491            public synchronized void clear() {
0492                Entry tab[] = table;
0493                modCount++;
0494                for (int index = tab.length; --index >= 0;)
0495                    tab[index] = null;
0496                count = 0;
0497            }
0498
0499            /**
0500             * Creates a shallow copy of this hashtable. All the structure of the
0501             * hashtable itself is copied, but the keys and values are not cloned.
0502             * This is a relatively expensive operation.
0503             *
0504             * @return  a clone of the hashtable
0505             */
0506            public synchronized Object clone() {
0507                try {
0508                    Hashtable<K, V> t = (Hashtable<K, V>) super .clone();
0509                    t.table = new Entry[table.length];
0510                    for (int i = table.length; i-- > 0;) {
0511                        t.table[i] = (table[i] != null) ? (Entry<K, V>) table[i]
0512                                .clone()
0513                                : null;
0514                    }
0515                    t.keySet = null;
0516                    t.entrySet = null;
0517                    t.values = null;
0518                    t.modCount = 0;
0519                    return t;
0520                } catch (CloneNotSupportedException e) {
0521                    // this shouldn't happen, since we are Cloneable
0522                    throw new InternalError();
0523                }
0524            }
0525
0526            /**
0527             * Returns a string representation of this <tt>Hashtable</tt> object
0528             * in the form of a set of entries, enclosed in braces and separated
0529             * by the ASCII characters "<tt>,&nbsp;</tt>" (comma and space). Each
0530             * entry is rendered as the key, an equals sign <tt>=</tt>, and the
0531             * associated element, where the <tt>toString</tt> method is used to
0532             * convert the key and element to strings.
0533             *
0534             * @return  a string representation of this hashtable
0535             */
0536            public synchronized String toString() {
0537                int max = size() - 1;
0538                if (max == -1)
0539                    return "{}";
0540
0541                StringBuilder sb = new StringBuilder();
0542                Iterator<Map.Entry<K, V>> it = entrySet().iterator();
0543
0544                sb.append('{');
0545                for (int i = 0;; i++) {
0546                    Map.Entry<K, V> e = it.next();
0547                    K key = e.getKey();
0548                    V value = e.getValue();
0549                    sb.append(key == this  ? "(this Map)" : key.toString());
0550                    sb.append('=');
0551                    sb.append(value == this  ? "(this Map)" : value.toString());
0552
0553                    if (i == max)
0554                        return sb.append('}').toString();
0555                    sb.append(", ");
0556                }
0557            }
0558
0559            private <T> Enumeration<T> getEnumeration(int type) {
0560                if (count == 0) {
0561                    return Collections.emptyEnumeration();
0562                } else {
0563                    return new Enumerator<T>(type, false);
0564                }
0565            }
0566
0567            private <T> Iterator<T> getIterator(int type) {
0568                if (count == 0) {
0569                    return Collections.emptyIterator();
0570                } else {
0571                    return new Enumerator<T>(type, true);
0572                }
0573            }
0574
0575            // Views
0576
0577            /**
0578             * Each of these fields are initialized to contain an instance of the
0579             * appropriate view the first time this view is requested.  The views are
0580             * stateless, so there's no reason to create more than one of each.
0581             */
0582            private transient volatile Set<K> keySet = null;
0583            private transient volatile Set<Map.Entry<K, V>> entrySet = null;
0584            private transient volatile Collection<V> values = null;
0585
0586            /**
0587             * Returns a {@link Set} view of the keys contained in this map.
0588             * The set is backed by the map, so changes to the map are
0589             * reflected in the set, and vice-versa.  If the map is modified
0590             * while an iteration over the set is in progress (except through
0591             * the iterator's own <tt>remove</tt> operation), the results of
0592             * the iteration are undefined.  The set supports element removal,
0593             * which removes the corresponding mapping from the map, via the
0594             * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
0595             * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
0596             * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
0597             * operations.
0598             *
0599             * @since 1.2
0600             */
0601            public Set<K> keySet() {
0602                if (keySet == null)
0603                    keySet = Collections.synchronizedSet(new KeySet(), this );
0604                return keySet;
0605            }
0606
0607            private class KeySet extends AbstractSet<K> {
0608                public Iterator<K> iterator() {
0609                    return getIterator(KEYS);
0610                }
0611
0612                public int size() {
0613                    return count;
0614                }
0615
0616                public boolean contains(Object o) {
0617                    return containsKey(o);
0618                }
0619
0620                public boolean remove(Object o) {
0621                    return Hashtable.this .remove(o) != null;
0622                }
0623
0624                public void clear() {
0625                    Hashtable.this .clear();
0626                }
0627            }
0628
0629            /**
0630             * Returns a {@link Set} view of the mappings contained in this map.
0631             * The set is backed by the map, so changes to the map are
0632             * reflected in the set, and vice-versa.  If the map is modified
0633             * while an iteration over the set is in progress (except through
0634             * the iterator's own <tt>remove</tt> operation, or through the
0635             * <tt>setValue</tt> operation on a map entry returned by the
0636             * iterator) the results of the iteration are undefined.  The set
0637             * supports element removal, which removes the corresponding
0638             * mapping from the map, via the <tt>Iterator.remove</tt>,
0639             * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
0640             * <tt>clear</tt> operations.  It does not support the
0641             * <tt>add</tt> or <tt>addAll</tt> operations.
0642             *
0643             * @since 1.2
0644             */
0645            public Set<Map.Entry<K, V>> entrySet() {
0646                if (entrySet == null)
0647                    entrySet = Collections
0648                            .synchronizedSet(new EntrySet(), this );
0649                return entrySet;
0650            }
0651
0652            private class EntrySet extends AbstractSet<Map.Entry<K, V>> {
0653                public Iterator<Map.Entry<K, V>> iterator() {
0654                    return getIterator(ENTRIES);
0655                }
0656
0657                public boolean add(Map.Entry<K, V> o) {
0658                    return super .add(o);
0659                }
0660
0661                public boolean contains(Object o) {
0662                    if (!(o instanceof  Map.Entry))
0663                        return false;
0664                    Map.Entry entry = (Map.Entry) o;
0665                    Object key = entry.getKey();
0666                    Entry[] tab = table;
0667                    int hash = key.hashCode();
0668                    int index = (hash & 0x7FFFFFFF) % tab.length;
0669
0670                    for (Entry e = tab[index]; e != null; e = e.next)
0671                        if (e.hash == hash && e.equals(entry))
0672                            return true;
0673                    return false;
0674                }
0675
0676                public boolean remove(Object o) {
0677                    if (!(o instanceof  Map.Entry))
0678                        return false;
0679                    Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
0680                    K key = entry.getKey();
0681                    Entry[] tab = table;
0682                    int hash = key.hashCode();
0683                    int index = (hash & 0x7FFFFFFF) % tab.length;
0684
0685                    for (Entry<K, V> e = tab[index], prev = null; e != null; prev = e, e = e.next) {
0686                        if (e.hash == hash && e.equals(entry)) {
0687                            modCount++;
0688                            if (prev != null)
0689                                prev.next = e.next;
0690                            else
0691                                tab[index] = e.next;
0692
0693                            count--;
0694                            e.value = null;
0695                            return true;
0696                        }
0697                    }
0698                    return false;
0699                }
0700
0701                public int size() {
0702                    return count;
0703                }
0704
0705                public void clear() {
0706                    Hashtable.this .clear();
0707                }
0708            }
0709
0710            /**
0711             * Returns a {@link Collection} view of the values contained in this map.
0712             * The collection is backed by the map, so changes to the map are
0713             * reflected in the collection, and vice-versa.  If the map is
0714             * modified while an iteration over the collection is in progress
0715             * (except through the iterator's own <tt>remove</tt> operation),
0716             * the results of the iteration are undefined.  The collection
0717             * supports element removal, which removes the corresponding
0718             * mapping from the map, via the <tt>Iterator.remove</tt>,
0719             * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
0720             * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
0721             * support the <tt>add</tt> or <tt>addAll</tt> operations.
0722             *
0723             * @since 1.2
0724             */
0725            public Collection<V> values() {
0726                if (values == null)
0727                    values = Collections.synchronizedCollection(
0728                            new ValueCollection(), this );
0729                return values;
0730            }
0731
0732            private class ValueCollection extends AbstractCollection<V> {
0733                public Iterator<V> iterator() {
0734                    return getIterator(VALUES);
0735                }
0736
0737                public int size() {
0738                    return count;
0739                }
0740
0741                public boolean contains(Object o) {
0742                    return containsValue(o);
0743                }
0744
0745                public void clear() {
0746                    Hashtable.this .clear();
0747                }
0748            }
0749
0750            // Comparison and hashing
0751
0752            /**
0753             * Compares the specified Object with this Map for equality,
0754             * as per the definition in the Map interface.
0755             *
0756             * @param  o object to be compared for equality with this hashtable
0757             * @return true if the specified Object is equal to this Map
0758             * @see Map#equals(Object)
0759             * @since 1.2
0760             */
0761            public synchronized boolean equals(Object o) {
0762                if (o == this )
0763                    return true;
0764
0765                if (!(o instanceof  Map))
0766                    return false;
0767                Map<K, V> t = (Map<K, V>) o;
0768                if (t.size() != size())
0769                    return false;
0770
0771                try {
0772                    Iterator<Map.Entry<K, V>> i = entrySet().iterator();
0773                    while (i.hasNext()) {
0774                        Map.Entry<K, V> e = i.next();
0775                        K key = e.getKey();
0776                        V value = e.getValue();
0777                        if (value == null) {
0778                            if (!(t.get(key) == null && t.containsKey(key)))
0779                                return false;
0780                        } else {
0781                            if (!value.equals(t.get(key)))
0782                                return false;
0783                        }
0784                    }
0785                } catch (ClassCastException unused) {
0786                    return false;
0787                } catch (NullPointerException unused) {
0788                    return false;
0789                }
0790
0791                return true;
0792            }
0793
0794            /**
0795             * Returns the hash code value for this Map as per the definition in the
0796             * Map interface.
0797             *
0798             * @see Map#hashCode()
0799             * @since 1.2
0800             */
0801            public synchronized int hashCode() {
0802                /*
0803                 * This code detects the recursion caused by computing the hash code
0804                 * of a self-referential hash table and prevents the stack overflow
0805                 * that would otherwise result.  This allows certain 1.1-era
0806                 * applets with self-referential hash tables to work.  This code
0807                 * abuses the loadFactor field to do double-duty as a hashCode
0808                 * in progress flag, so as not to worsen the space performance.
0809                 * A negative load factor indicates that hash code computation is
0810                 * in progress.
0811                 */
0812                int h = 0;
0813                if (count == 0 || loadFactor < 0)
0814                    return h; // Returns zero
0815
0816                loadFactor = -loadFactor; // Mark hashCode computation in progress
0817                Entry[] tab = table;
0818                for (int i = 0; i < tab.length; i++)
0819                    for (Entry e = tab[i]; e != null; e = e.next)
0820                        h += e.key.hashCode() ^ e.value.hashCode();
0821                loadFactor = -loadFactor; // Mark hashCode computation complete
0822
0823                return h;
0824            }
0825
0826            /**
0827             * Save the state of the Hashtable to a stream (i.e., serialize it).
0828             *
0829             * @serialData The <i>capacity</i> of the Hashtable (the length of the
0830             *		   bucket array) is emitted (int), followed by the
0831             *		   <i>size</i> of the Hashtable (the number of key-value
0832             *		   mappings), followed by the key (Object) and value (Object)
0833             *		   for each key-value mapping represented by the Hashtable
0834             *		   The key-value mappings are emitted in no particular order.
0835             */
0836            private synchronized void writeObject(java.io.ObjectOutputStream s)
0837                    throws IOException {
0838                // Write out the length, threshold, loadfactor
0839                s.defaultWriteObject();
0840
0841                // Write out length, count of elements and then the key/value objects
0842                s.writeInt(table.length);
0843                s.writeInt(count);
0844                for (int index = table.length - 1; index >= 0; index--) {
0845                    Entry entry = table[index];
0846
0847                    while (entry != null) {
0848                        s.writeObject(entry.key);
0849                        s.writeObject(entry.value);
0850                        entry = entry.next;
0851                    }
0852                }
0853            }
0854
0855            /**
0856             * Reconstitute the Hashtable from a stream (i.e., deserialize it).
0857             */
0858            private void readObject(java.io.ObjectInputStream s)
0859                    throws IOException, ClassNotFoundException {
0860                // Read in the length, threshold, and loadfactor
0861                s.defaultReadObject();
0862
0863                // Read the original length of the array and number of elements
0864                int origlength = s.readInt();
0865                int elements = s.readInt();
0866
0867                // Compute new size with a bit of room 5% to grow but
0868                // no larger than the original size.  Make the length
0869                // odd if it's large enough, this helps distribute the entries.
0870                // Guard against the length ending up zero, that's not valid.
0871                int length = (int) (elements * loadFactor) + (elements / 20)
0872                        + 3;
0873                if (length > elements && (length & 1) == 0)
0874                    length--;
0875                if (origlength > 0 && length > origlength)
0876                    length = origlength;
0877
0878                Entry[] table = new Entry[length];
0879                count = 0;
0880
0881                // Read the number of elements and then all the key/value objects
0882                for (; elements > 0; elements--) {
0883                    K key = (K) s.readObject();
0884                    V value = (V) s.readObject();
0885                    // synch could be eliminated for performance
0886                    reconstitutionPut(table, key, value);
0887                }
0888                this .table = table;
0889            }
0890
0891            /**
0892             * The put method used by readObject. This is provided because put
0893             * is overridable and should not be called in readObject since the
0894             * subclass will not yet be initialized.
0895             *
0896             * <p>This differs from the regular put method in several ways. No
0897             * checking for rehashing is necessary since the number of elements
0898             * initially in the table is known. The modCount is not incremented
0899             * because we are creating a new instance. Also, no return value
0900             * is needed.
0901             */
0902            private void reconstitutionPut(Entry[] tab, K key, V value)
0903                    throws StreamCorruptedException {
0904                if (value == null) {
0905                    throw new java.io.StreamCorruptedException();
0906                }
0907                // Makes sure the key is not already in the hashtable.
0908                // This should not happen in deserialized version.
0909                int hash = key.hashCode();
0910                int index = (hash & 0x7FFFFFFF) % tab.length;
0911                for (Entry<K, V> e = tab[index]; e != null; e = e.next) {
0912                    if ((e.hash == hash) && e.key.equals(key)) {
0913                        throw new java.io.StreamCorruptedException();
0914                    }
0915                }
0916                // Creates the new entry.
0917                Entry<K, V> e = tab[index];
0918                tab[index] = new Entry<K, V>(hash, key, value, e);
0919                count++;
0920            }
0921
0922            /**
0923             * Hashtable collision list.
0924             */
0925            private static class Entry<K, V> implements  Map.Entry<K, V> {
0926                int hash;
0927                K key;
0928                V value;
0929                Entry<K, V> next;
0930
0931                protected Entry(int hash, K key, V value, Entry<K, V> next) {
0932                    this .hash = hash;
0933                    this .key = key;
0934                    this .value = value;
0935                    this .next = next;
0936                }
0937
0938                protected Object clone() {
0939                    return new Entry<K, V>(hash, key, value,
0940                            (next == null ? null : (Entry<K, V>) next.clone()));
0941                }
0942
0943                // Map.Entry Ops
0944
0945                public K getKey() {
0946                    return key;
0947                }
0948
0949                public V getValue() {
0950                    return value;
0951                }
0952
0953                public V setValue(V value) {
0954                    if (value == null)
0955                        throw new NullPointerException();
0956
0957                    V oldValue = this .value;
0958                    this .value = value;
0959                    return oldValue;
0960                }
0961
0962                public boolean equals(Object o) {
0963                    if (!(o instanceof  Map.Entry))
0964                        return false;
0965                    Map.Entry e = (Map.Entry) o;
0966
0967                    return (key == null ? e.getKey() == null : key.equals(e
0968                            .getKey()))
0969                            && (value == null ? e.getValue() == null : value
0970                                    .equals(e.getValue()));
0971                }
0972
0973                public int hashCode() {
0974                    return hash ^ (value == null ? 0 : value.hashCode());
0975                }
0976
0977                public String toString() {
0978                    return key.toString() + "=" + value.toString();
0979                }
0980            }
0981
0982            // Types of Enumerations/Iterations
0983            private static final int KEYS = 0;
0984            private static final int VALUES = 1;
0985            private static final int ENTRIES = 2;
0986
0987            /**
0988             * A hashtable enumerator class.  This class implements both the
0989             * Enumeration and Iterator interfaces, but individual instances
0990             * can be created with the Iterator methods disabled.  This is necessary
0991             * to avoid unintentionally increasing the capabilities granted a user
0992             * by passing an Enumeration.
0993             */
0994            private class Enumerator<T> implements  Enumeration<T>, Iterator<T> {
0995                Entry[] table = Hashtable.this .table;
0996                int index = table.length;
0997                Entry<K, V> entry = null;
0998                Entry<K, V> lastReturned = null;
0999                int type;
1000
1001                /**
1002                 * Indicates whether this Enumerator is serving as an Iterator
1003                 * or an Enumeration.  (true -> Iterator).
1004                 */
1005                boolean iterator;
1006
1007                /**
1008                 * The modCount value that the iterator believes that the backing
1009                 * Hashtable should have.  If this expectation is violated, the iterator
1010                 * has detected concurrent modification.
1011                 */
1012                protected int expectedModCount = modCount;
1013
1014                Enumerator(int type, boolean iterator) {
1015                    this .type = type;
1016                    this .iterator = iterator;
1017                }
1018
1019                public boolean hasMoreElements() {
1020                    Entry<K, V> e = entry;
1021                    int i = index;
1022                    Entry[] t = table;
1023                    /* Use locals for faster loop iteration */
1024                    while (e == null && i > 0) {
1025                        e = t[--i];
1026                    }
1027                    entry = e;
1028                    index = i;
1029                    return e != null;
1030                }
1031
1032                public T nextElement() {
1033                    Entry<K, V> et = entry;
1034                    int i = index;
1035                    Entry[] t = table;
1036                    /* Use locals for faster loop iteration */
1037                    while (et == null && i > 0) {
1038                        et = t[--i];
1039                    }
1040                    entry = et;
1041                    index = i;
1042                    if (et != null) {
1043                        Entry<K, V> e = lastReturned = entry;
1044                        entry = e.next;
1045                        return type == KEYS ? (T) e.key
1046                                : (type == VALUES ? (T) e.value : (T) e);
1047                    }
1048                    throw new NoSuchElementException("Hashtable Enumerator");
1049                }
1050
1051                // Iterator methods
1052                public boolean hasNext() {
1053                    return hasMoreElements();
1054                }
1055
1056                public T next() {
1057                    if (modCount != expectedModCount)
1058                        throw new ConcurrentModificationException();
1059                    return nextElement();
1060                }
1061
1062                public void remove() {
1063                    if (!iterator)
1064                        throw new UnsupportedOperationException();
1065                    if (lastReturned == null)
1066                        throw new IllegalStateException("Hashtable Enumerator");
1067                    if (modCount != expectedModCount)
1068                        throw new ConcurrentModificationException();
1069
1070                    synchronized (Hashtable.this ) {
1071                        Entry[] tab = Hashtable.this .table;
1072                        int index = (lastReturned.hash & 0x7FFFFFFF)
1073                                % tab.length;
1074
1075                        for (Entry<K, V> e = tab[index], prev = null; e != null; prev = e, e = e.next) {
1076                            if (e == lastReturned) {
1077                                modCount++;
1078                                expectedModCount++;
1079                                if (prev == null)
1080                                    tab[index] = e.next;
1081                                else
1082                                    prev.next = e.next;
1083                                count--;
1084                                lastReturned = null;
1085                                return;
1086                            }
1087                        }
1088                        throw new ConcurrentModificationException();
1089                    }
1090                }
1091            }
1092        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.