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

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 geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
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:        }
w_ww.___ja_v__a___2___s.co__m___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.