Source Code Cross Referenced for MultiKeyMap.java in  » Library » Apache-common-Collections » org » apache » commons » collections » map » 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 » Library » Apache common Collections » org.apache.commons.collections.map 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *  Copyright 2004 The Apache Software Foundation
003:         *
004:         *  Licensed under the Apache License, Version 2.0 (the "License");
005:         *  you may not use this file except in compliance with the License.
006:         *  You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         *  Unless required by applicable law or agreed to in writing, software
011:         *  distributed under the License is distributed on an "AS IS" BASIS,
012:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         *  See the License for the specific language governing permissions and
014:         *  limitations under the License.
015:         */
016:        package org.apache.commons.collections.map;
017:
018:        import java.io.Serializable;
019:        import java.util.Collection;
020:        import java.util.Iterator;
021:        import java.util.Map;
022:        import java.util.Set;
023:
024:        import org.apache.commons.collections.IterableMap;
025:        import org.apache.commons.collections.MapIterator;
026:        import org.apache.commons.collections.keyvalue.MultiKey;
027:
028:        /**
029:         * A <code>Map</code> implementation that uses multiple keys to map the value.
030:         * <p>
031:         * This class is the most efficient way to uses multiple keys to map to a value.
032:         * The best way to use this class is via the additional map-style methods.
033:         * These provide <code>get</code>, <code>containsKey</code>, <code>put</code> and
034:         * <code>remove</code> for individual keys which operate without extra object creation.
035:         * <p>
036:         * The additional methods are the main interface of this map.
037:         * As such, you will not normally hold this map in a variable of type <code>Map</code>.
038:         * <p>
039:         * The normal map methods take in and return a {@link MultiKey}.
040:         * If you try to use <code>put()</code> with any other object type a
041:         * <code>ClassCastException</code> is thrown. If you try to use <code>null</code> as
042:         * the key in <code>put()</code> a <code>NullPointerException</code> is thrown.
043:         * <p>
044:         * This map is implemented as a decorator of a <code>AbstractHashedMap</code> which
045:         * enables extra behaviour to be added easily.
046:         * <ul>
047:         * <li><code>MultiKeyMap.decorate(new LinkedMap())</code> creates an ordered map.
048:         * <li><code>MultiKeyMap.decorate(new LRUMap())</code> creates an least recently used map.
049:         * <li><code>MultiKeyMap.decorate(new ReferenceMap())</code> creates a garbage collector sensitive map.
050:         * </ul>
051:         * Note that <code>IdentityMap</code> and <code>ReferenceIdentityMap</code> are unsuitable
052:         * for use as the key comparison would work on the whole MultiKey, not the elements within.
053:         * <p>
054:         * As an example, consider a least recently used cache that uses a String airline code
055:         * and a Locale to lookup the airline's name:
056:         * <pre>
057:         * private MultiKeyMap cache = MultiKeyMap.decorate(new LRUMap(50));
058:         * 
059:         * public String getAirlineName(String code, String locale) {
060:         *   String name = (String) cache.get(code, locale);
061:         *   if (name == null) {
062:         *     name = getAirlineNameFromDB(code, locale);
063:         *     cache.put(code, locale, name);
064:         *   }
065:         *   return name;
066:         * }
067:         * </pre>
068:         * <p>
069:         * <strong>Note that MultiKeyMap is not synchronized and is not thread-safe.</strong>
070:         * If you wish to use this map from multiple threads concurrently, you must use
071:         * appropriate synchronization. This class may throw exceptions when accessed
072:         * by concurrent threads without synchronization.
073:         *
074:         * @since Commons Collections 3.1
075:         * @version $Revision: 348007 $ $Date: 2005-11-21 22:52:57 +0000 (Mon, 21 Nov 2005) $
076:         *
077:         * @author Stephen Colebourne
078:         */
079:        public class MultiKeyMap implements  IterableMap, Serializable {
080:
081:            /** Serialisation version */
082:            private static final long serialVersionUID = -1788199231038721040L;
083:
084:            /** The decorated map */
085:            protected final AbstractHashedMap map;
086:
087:            //-----------------------------------------------------------------------
088:            /**
089:             * Decorates the specified map to add the MultiKeyMap API and fast query.
090:             * The map must not be null and must be empty.
091:             *
092:             * @param map  the map to decorate, not null
093:             * @throws IllegalArgumentException if the map is null or not empty
094:             */
095:            public static MultiKeyMap decorate(AbstractHashedMap map) {
096:                if (map == null) {
097:                    throw new IllegalArgumentException("Map must not be null");
098:                }
099:                if (map.size() > 0) {
100:                    throw new IllegalArgumentException("Map must be empty");
101:                }
102:                return new MultiKeyMap(map);
103:            }
104:
105:            //-----------------------------------------------------------------------    
106:            /**
107:             * Constructs a new MultiKeyMap that decorates a <code>HashedMap</code>.
108:             */
109:            public MultiKeyMap() {
110:                super ();
111:                map = new HashedMap();
112:            }
113:
114:            /**
115:             * Constructor that decorates the specified map and is called from
116:             * {@link #decorate(AbstractHashedMap)}.
117:             * The map must not be null and should be empty or only contain valid keys.
118:             * This constructor performs no validation.
119:             *
120:             * @param map  the map to decorate
121:             */
122:            protected MultiKeyMap(AbstractHashedMap map) {
123:                super ();
124:                this .map = map;
125:            }
126:
127:            //-----------------------------------------------------------------------
128:            /**
129:             * Gets the value mapped to the specified multi-key.
130:             * 
131:             * @param key1  the first key
132:             * @param key2  the second key
133:             * @return the mapped value, null if no match
134:             */
135:            public Object get(Object key1, Object key2) {
136:                int hashCode = hash(key1, key2);
137:                AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(
138:                        hashCode, map.data.length)];
139:                while (entry != null) {
140:                    if (entry.hashCode == hashCode
141:                            && isEqualKey(entry, key1, key2)) {
142:                        return entry.getValue();
143:                    }
144:                    entry = entry.next;
145:                }
146:                return null;
147:            }
148:
149:            /**
150:             * Checks whether the map contains the specified multi-key.
151:             * 
152:             * @param key1  the first key
153:             * @param key2  the second key
154:             * @return true if the map contains the key
155:             */
156:            public boolean containsKey(Object key1, Object key2) {
157:                int hashCode = hash(key1, key2);
158:                AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(
159:                        hashCode, map.data.length)];
160:                while (entry != null) {
161:                    if (entry.hashCode == hashCode
162:                            && isEqualKey(entry, key1, key2)) {
163:                        return true;
164:                    }
165:                    entry = entry.next;
166:                }
167:                return false;
168:            }
169:
170:            /**
171:             * Stores the value against the specified multi-key.
172:             * 
173:             * @param key1  the first key
174:             * @param key2  the second key
175:             * @param value  the value to store
176:             * @return the value previously mapped to this combined key, null if none
177:             */
178:            public Object put(Object key1, Object key2, Object value) {
179:                int hashCode = hash(key1, key2);
180:                int index = map.hashIndex(hashCode, map.data.length);
181:                AbstractHashedMap.HashEntry entry = map.data[index];
182:                while (entry != null) {
183:                    if (entry.hashCode == hashCode
184:                            && isEqualKey(entry, key1, key2)) {
185:                        Object oldValue = entry.getValue();
186:                        map.updateEntry(entry, value);
187:                        return oldValue;
188:                    }
189:                    entry = entry.next;
190:                }
191:
192:                map
193:                        .addMapping(index, hashCode, new MultiKey(key1, key2),
194:                                value);
195:                return null;
196:            }
197:
198:            /**
199:             * Removes the specified multi-key from this map.
200:             * 
201:             * @param key1  the first key
202:             * @param key2  the second key
203:             * @return the value mapped to the removed key, null if key not in map
204:             */
205:            public Object remove(Object key1, Object key2) {
206:                int hashCode = hash(key1, key2);
207:                int index = map.hashIndex(hashCode, map.data.length);
208:                AbstractHashedMap.HashEntry entry = map.data[index];
209:                AbstractHashedMap.HashEntry previous = null;
210:                while (entry != null) {
211:                    if (entry.hashCode == hashCode
212:                            && isEqualKey(entry, key1, key2)) {
213:                        Object oldValue = entry.getValue();
214:                        map.removeMapping(entry, index, previous);
215:                        return oldValue;
216:                    }
217:                    previous = entry;
218:                    entry = entry.next;
219:                }
220:                return null;
221:            }
222:
223:            /**
224:             * Gets the hash code for the specified multi-key.
225:             * 
226:             * @param key1  the first key
227:             * @param key2  the second key
228:             * @return the hash code
229:             */
230:            protected int hash(Object key1, Object key2) {
231:                int h = 0;
232:                if (key1 != null) {
233:                    h ^= key1.hashCode();
234:                }
235:                if (key2 != null) {
236:                    h ^= key2.hashCode();
237:                }
238:                h += ~(h << 9);
239:                h ^= (h >>> 14);
240:                h += (h << 4);
241:                h ^= (h >>> 10);
242:                return h;
243:            }
244:
245:            /**
246:             * Is the key equal to the combined key.
247:             * 
248:             * @param entry  the entry to compare to
249:             * @param key1  the first key
250:             * @param key2  the second key
251:             * @return true if the key matches
252:             */
253:            protected boolean isEqualKey(AbstractHashedMap.HashEntry entry,
254:                    Object key1, Object key2) {
255:                MultiKey multi = (MultiKey) entry.getKey();
256:                return multi.size() == 2
257:                        && (key1 == null ? multi.getKey(0) == null : key1
258:                                .equals(multi.getKey(0)))
259:                        && (key2 == null ? multi.getKey(1) == null : key2
260:                                .equals(multi.getKey(1)));
261:            }
262:
263:            //-----------------------------------------------------------------------
264:            /**
265:             * Gets the value mapped to the specified multi-key.
266:             * 
267:             * @param key1  the first key
268:             * @param key2  the second key
269:             * @param key3  the third key
270:             * @return the mapped value, null if no match
271:             */
272:            public Object get(Object key1, Object key2, Object key3) {
273:                int hashCode = hash(key1, key2, key3);
274:                AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(
275:                        hashCode, map.data.length)];
276:                while (entry != null) {
277:                    if (entry.hashCode == hashCode
278:                            && isEqualKey(entry, key1, key2, key3)) {
279:                        return entry.getValue();
280:                    }
281:                    entry = entry.next;
282:                }
283:                return null;
284:            }
285:
286:            /**
287:             * Checks whether the map contains the specified multi-key.
288:             * 
289:             * @param key1  the first key
290:             * @param key2  the second key
291:             * @param key3  the third key
292:             * @return true if the map contains the key
293:             */
294:            public boolean containsKey(Object key1, Object key2, Object key3) {
295:                int hashCode = hash(key1, key2, key3);
296:                AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(
297:                        hashCode, map.data.length)];
298:                while (entry != null) {
299:                    if (entry.hashCode == hashCode
300:                            && isEqualKey(entry, key1, key2, key3)) {
301:                        return true;
302:                    }
303:                    entry = entry.next;
304:                }
305:                return false;
306:            }
307:
308:            /**
309:             * Stores the value against the specified multi-key.
310:             * 
311:             * @param key1  the first key
312:             * @param key2  the second key
313:             * @param key3  the third key
314:             * @param value  the value to store
315:             * @return the value previously mapped to this combined key, null if none
316:             */
317:            public Object put(Object key1, Object key2, Object key3,
318:                    Object value) {
319:                int hashCode = hash(key1, key2, key3);
320:                int index = map.hashIndex(hashCode, map.data.length);
321:                AbstractHashedMap.HashEntry entry = map.data[index];
322:                while (entry != null) {
323:                    if (entry.hashCode == hashCode
324:                            && isEqualKey(entry, key1, key2, key3)) {
325:                        Object oldValue = entry.getValue();
326:                        map.updateEntry(entry, value);
327:                        return oldValue;
328:                    }
329:                    entry = entry.next;
330:                }
331:
332:                map.addMapping(index, hashCode, new MultiKey(key1, key2, key3),
333:                        value);
334:                return null;
335:            }
336:
337:            /**
338:             * Removes the specified multi-key from this map.
339:             * 
340:             * @param key1  the first key
341:             * @param key2  the second key
342:             * @param key3  the third key
343:             * @return the value mapped to the removed key, null if key not in map
344:             */
345:            public Object remove(Object key1, Object key2, Object key3) {
346:                int hashCode = hash(key1, key2, key3);
347:                int index = map.hashIndex(hashCode, map.data.length);
348:                AbstractHashedMap.HashEntry entry = map.data[index];
349:                AbstractHashedMap.HashEntry previous = null;
350:                while (entry != null) {
351:                    if (entry.hashCode == hashCode
352:                            && isEqualKey(entry, key1, key2, key3)) {
353:                        Object oldValue = entry.getValue();
354:                        map.removeMapping(entry, index, previous);
355:                        return oldValue;
356:                    }
357:                    previous = entry;
358:                    entry = entry.next;
359:                }
360:                return null;
361:            }
362:
363:            /**
364:             * Gets the hash code for the specified multi-key.
365:             * 
366:             * @param key1  the first key
367:             * @param key2  the second key
368:             * @param key3  the third key
369:             * @return the hash code
370:             */
371:            protected int hash(Object key1, Object key2, Object key3) {
372:                int h = 0;
373:                if (key1 != null) {
374:                    h ^= key1.hashCode();
375:                }
376:                if (key2 != null) {
377:                    h ^= key2.hashCode();
378:                }
379:                if (key3 != null) {
380:                    h ^= key3.hashCode();
381:                }
382:                h += ~(h << 9);
383:                h ^= (h >>> 14);
384:                h += (h << 4);
385:                h ^= (h >>> 10);
386:                return h;
387:            }
388:
389:            /**
390:             * Is the key equal to the combined key.
391:             * 
392:             * @param entry  the entry to compare to
393:             * @param key1  the first key
394:             * @param key2  the second key
395:             * @param key3  the third key
396:             * @return true if the key matches
397:             */
398:            protected boolean isEqualKey(AbstractHashedMap.HashEntry entry,
399:                    Object key1, Object key2, Object key3) {
400:                MultiKey multi = (MultiKey) entry.getKey();
401:                return multi.size() == 3
402:                        && (key1 == null ? multi.getKey(0) == null : key1
403:                                .equals(multi.getKey(0)))
404:                        && (key2 == null ? multi.getKey(1) == null : key2
405:                                .equals(multi.getKey(1)))
406:                        && (key3 == null ? multi.getKey(2) == null : key3
407:                                .equals(multi.getKey(2)));
408:            }
409:
410:            //-----------------------------------------------------------------------
411:            /**
412:             * Gets the value mapped to the specified multi-key.
413:             * 
414:             * @param key1  the first key
415:             * @param key2  the second key
416:             * @param key3  the third key
417:             * @param key4  the fourth key
418:             * @return the mapped value, null if no match
419:             */
420:            public Object get(Object key1, Object key2, Object key3, Object key4) {
421:                int hashCode = hash(key1, key2, key3, key4);
422:                AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(
423:                        hashCode, map.data.length)];
424:                while (entry != null) {
425:                    if (entry.hashCode == hashCode
426:                            && isEqualKey(entry, key1, key2, key3, key4)) {
427:                        return entry.getValue();
428:                    }
429:                    entry = entry.next;
430:                }
431:                return null;
432:            }
433:
434:            /**
435:             * Checks whether the map contains the specified multi-key.
436:             * 
437:             * @param key1  the first key
438:             * @param key2  the second key
439:             * @param key3  the third key
440:             * @param key4  the fourth key
441:             * @return true if the map contains the key
442:             */
443:            public boolean containsKey(Object key1, Object key2, Object key3,
444:                    Object key4) {
445:                int hashCode = hash(key1, key2, key3, key4);
446:                AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(
447:                        hashCode, map.data.length)];
448:                while (entry != null) {
449:                    if (entry.hashCode == hashCode
450:                            && isEqualKey(entry, key1, key2, key3, key4)) {
451:                        return true;
452:                    }
453:                    entry = entry.next;
454:                }
455:                return false;
456:            }
457:
458:            /**
459:             * Stores the value against the specified multi-key.
460:             * 
461:             * @param key1  the first key
462:             * @param key2  the second key
463:             * @param key3  the third key
464:             * @param key4  the fourth key
465:             * @param value  the value to store
466:             * @return the value previously mapped to this combined key, null if none
467:             */
468:            public Object put(Object key1, Object key2, Object key3,
469:                    Object key4, Object value) {
470:                int hashCode = hash(key1, key2, key3, key4);
471:                int index = map.hashIndex(hashCode, map.data.length);
472:                AbstractHashedMap.HashEntry entry = map.data[index];
473:                while (entry != null) {
474:                    if (entry.hashCode == hashCode
475:                            && isEqualKey(entry, key1, key2, key3, key4)) {
476:                        Object oldValue = entry.getValue();
477:                        map.updateEntry(entry, value);
478:                        return oldValue;
479:                    }
480:                    entry = entry.next;
481:                }
482:
483:                map.addMapping(index, hashCode, new MultiKey(key1, key2, key3,
484:                        key4), value);
485:                return null;
486:            }
487:
488:            /**
489:             * Removes the specified multi-key from this map.
490:             * 
491:             * @param key1  the first key
492:             * @param key2  the second key
493:             * @param key3  the third key
494:             * @param key4  the fourth key
495:             * @return the value mapped to the removed key, null if key not in map
496:             */
497:            public Object remove(Object key1, Object key2, Object key3,
498:                    Object key4) {
499:                int hashCode = hash(key1, key2, key3, key4);
500:                int index = map.hashIndex(hashCode, map.data.length);
501:                AbstractHashedMap.HashEntry entry = map.data[index];
502:                AbstractHashedMap.HashEntry previous = null;
503:                while (entry != null) {
504:                    if (entry.hashCode == hashCode
505:                            && isEqualKey(entry, key1, key2, key3, key4)) {
506:                        Object oldValue = entry.getValue();
507:                        map.removeMapping(entry, index, previous);
508:                        return oldValue;
509:                    }
510:                    previous = entry;
511:                    entry = entry.next;
512:                }
513:                return null;
514:            }
515:
516:            /**
517:             * Gets the hash code for the specified multi-key.
518:             * 
519:             * @param key1  the first key
520:             * @param key2  the second key
521:             * @param key3  the third key
522:             * @param key4  the fourth key
523:             * @return the hash code
524:             */
525:            protected int hash(Object key1, Object key2, Object key3,
526:                    Object key4) {
527:                int h = 0;
528:                if (key1 != null) {
529:                    h ^= key1.hashCode();
530:                }
531:                if (key2 != null) {
532:                    h ^= key2.hashCode();
533:                }
534:                if (key3 != null) {
535:                    h ^= key3.hashCode();
536:                }
537:                if (key4 != null) {
538:                    h ^= key4.hashCode();
539:                }
540:                h += ~(h << 9);
541:                h ^= (h >>> 14);
542:                h += (h << 4);
543:                h ^= (h >>> 10);
544:                return h;
545:            }
546:
547:            /**
548:             * Is the key equal to the combined key.
549:             * 
550:             * @param entry  the entry to compare to
551:             * @param key1  the first key
552:             * @param key2  the second key
553:             * @param key3  the third key
554:             * @param key4  the fourth key
555:             * @return true if the key matches
556:             */
557:            protected boolean isEqualKey(AbstractHashedMap.HashEntry entry,
558:                    Object key1, Object key2, Object key3, Object key4) {
559:                MultiKey multi = (MultiKey) entry.getKey();
560:                return multi.size() == 4
561:                        && (key1 == null ? multi.getKey(0) == null : key1
562:                                .equals(multi.getKey(0)))
563:                        && (key2 == null ? multi.getKey(1) == null : key2
564:                                .equals(multi.getKey(1)))
565:                        && (key3 == null ? multi.getKey(2) == null : key3
566:                                .equals(multi.getKey(2)))
567:                        && (key4 == null ? multi.getKey(3) == null : key4
568:                                .equals(multi.getKey(3)));
569:            }
570:
571:            //-----------------------------------------------------------------------
572:            /**
573:             * Gets the value mapped to the specified multi-key.
574:             * 
575:             * @param key1  the first key
576:             * @param key2  the second key
577:             * @param key3  the third key
578:             * @param key4  the fourth key
579:             * @param key5  the fifth key
580:             * @return the mapped value, null if no match
581:             */
582:            public Object get(Object key1, Object key2, Object key3,
583:                    Object key4, Object key5) {
584:                int hashCode = hash(key1, key2, key3, key4, key5);
585:                AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(
586:                        hashCode, map.data.length)];
587:                while (entry != null) {
588:                    if (entry.hashCode == hashCode
589:                            && isEqualKey(entry, key1, key2, key3, key4, key5)) {
590:                        return entry.getValue();
591:                    }
592:                    entry = entry.next;
593:                }
594:                return null;
595:            }
596:
597:            /**
598:             * Checks whether the map contains the specified multi-key.
599:             * 
600:             * @param key1  the first key
601:             * @param key2  the second key
602:             * @param key3  the third key
603:             * @param key4  the fourth key
604:             * @param key5  the fifth key
605:             * @return true if the map contains the key
606:             */
607:            public boolean containsKey(Object key1, Object key2, Object key3,
608:                    Object key4, Object key5) {
609:                int hashCode = hash(key1, key2, key3, key4, key5);
610:                AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(
611:                        hashCode, map.data.length)];
612:                while (entry != null) {
613:                    if (entry.hashCode == hashCode
614:                            && isEqualKey(entry, key1, key2, key3, key4, key5)) {
615:                        return true;
616:                    }
617:                    entry = entry.next;
618:                }
619:                return false;
620:            }
621:
622:            /**
623:             * Stores the value against the specified multi-key.
624:             * 
625:             * @param key1  the first key
626:             * @param key2  the second key
627:             * @param key3  the third key
628:             * @param key4  the fourth key
629:             * @param key5  the fifth key
630:             * @param value  the value to store
631:             * @return the value previously mapped to this combined key, null if none
632:             */
633:            public Object put(Object key1, Object key2, Object key3,
634:                    Object key4, Object key5, Object value) {
635:                int hashCode = hash(key1, key2, key3, key4, key5);
636:                int index = map.hashIndex(hashCode, map.data.length);
637:                AbstractHashedMap.HashEntry entry = map.data[index];
638:                while (entry != null) {
639:                    if (entry.hashCode == hashCode
640:                            && isEqualKey(entry, key1, key2, key3, key4, key5)) {
641:                        Object oldValue = entry.getValue();
642:                        map.updateEntry(entry, value);
643:                        return oldValue;
644:                    }
645:                    entry = entry.next;
646:                }
647:
648:                map.addMapping(index, hashCode, new MultiKey(key1, key2, key3,
649:                        key4, key5), value);
650:                return null;
651:            }
652:
653:            /**
654:             * Removes the specified multi-key from this map.
655:             * 
656:             * @param key1  the first key
657:             * @param key2  the second key
658:             * @param key3  the third key
659:             * @param key4  the fourth key
660:             * @param key5  the fifth key
661:             * @return the value mapped to the removed key, null if key not in map
662:             */
663:            public Object remove(Object key1, Object key2, Object key3,
664:                    Object key4, Object key5) {
665:                int hashCode = hash(key1, key2, key3, key4, key5);
666:                int index = map.hashIndex(hashCode, map.data.length);
667:                AbstractHashedMap.HashEntry entry = map.data[index];
668:                AbstractHashedMap.HashEntry previous = null;
669:                while (entry != null) {
670:                    if (entry.hashCode == hashCode
671:                            && isEqualKey(entry, key1, key2, key3, key4, key5)) {
672:                        Object oldValue = entry.getValue();
673:                        map.removeMapping(entry, index, previous);
674:                        return oldValue;
675:                    }
676:                    previous = entry;
677:                    entry = entry.next;
678:                }
679:                return null;
680:            }
681:
682:            /**
683:             * Gets the hash code for the specified multi-key.
684:             * 
685:             * @param key1  the first key
686:             * @param key2  the second key
687:             * @param key3  the third key
688:             * @param key4  the fourth key
689:             * @param key5  the fifth key
690:             * @return the hash code
691:             */
692:            protected int hash(Object key1, Object key2, Object key3,
693:                    Object key4, Object key5) {
694:                int h = 0;
695:                if (key1 != null) {
696:                    h ^= key1.hashCode();
697:                }
698:                if (key2 != null) {
699:                    h ^= key2.hashCode();
700:                }
701:                if (key3 != null) {
702:                    h ^= key3.hashCode();
703:                }
704:                if (key4 != null) {
705:                    h ^= key4.hashCode();
706:                }
707:                if (key5 != null) {
708:                    h ^= key5.hashCode();
709:                }
710:                h += ~(h << 9);
711:                h ^= (h >>> 14);
712:                h += (h << 4);
713:                h ^= (h >>> 10);
714:                return h;
715:            }
716:
717:            /**
718:             * Is the key equal to the combined key.
719:             * 
720:             * @param entry  the entry to compare to
721:             * @param key1  the first key
722:             * @param key2  the second key
723:             * @param key3  the third key
724:             * @param key4  the fourth key
725:             * @param key5  the fifth key
726:             * @return true if the key matches
727:             */
728:            protected boolean isEqualKey(AbstractHashedMap.HashEntry entry,
729:                    Object key1, Object key2, Object key3, Object key4,
730:                    Object key5) {
731:                MultiKey multi = (MultiKey) entry.getKey();
732:                return multi.size() == 5
733:                        && (key1 == null ? multi.getKey(0) == null : key1
734:                                .equals(multi.getKey(0)))
735:                        && (key2 == null ? multi.getKey(1) == null : key2
736:                                .equals(multi.getKey(1)))
737:                        && (key3 == null ? multi.getKey(2) == null : key3
738:                                .equals(multi.getKey(2)))
739:                        && (key4 == null ? multi.getKey(3) == null : key4
740:                                .equals(multi.getKey(3)))
741:                        && (key5 == null ? multi.getKey(4) == null : key5
742:                                .equals(multi.getKey(4)));
743:            }
744:
745:            //-----------------------------------------------------------------------
746:            /**
747:             * Removes all mappings where the first key is that specified.
748:             * <p>
749:             * This method removes all the mappings where the <code>MultiKey</code>
750:             * has one or more keys, and the first matches that specified.
751:             * 
752:             * @param key1  the first key
753:             * @return true if any elements were removed
754:             */
755:            public boolean removeAll(Object key1) {
756:                boolean modified = false;
757:                MapIterator it = mapIterator();
758:                while (it.hasNext()) {
759:                    MultiKey multi = (MultiKey) it.next();
760:                    if (multi.size() >= 1
761:                            && (key1 == null ? multi.getKey(0) == null : key1
762:                                    .equals(multi.getKey(0)))) {
763:                        it.remove();
764:                        modified = true;
765:                    }
766:                }
767:                return modified;
768:            }
769:
770:            /**
771:             * Removes all mappings where the first two keys are those specified.
772:             * <p>
773:             * This method removes all the mappings where the <code>MultiKey</code>
774:             * has two or more keys, and the first two match those specified.
775:             * 
776:             * @param key1  the first key
777:             * @param key2  the second key
778:             * @return true if any elements were removed
779:             */
780:            public boolean removeAll(Object key1, Object key2) {
781:                boolean modified = false;
782:                MapIterator it = mapIterator();
783:                while (it.hasNext()) {
784:                    MultiKey multi = (MultiKey) it.next();
785:                    if (multi.size() >= 2
786:                            && (key1 == null ? multi.getKey(0) == null : key1
787:                                    .equals(multi.getKey(0)))
788:                            && (key2 == null ? multi.getKey(1) == null : key2
789:                                    .equals(multi.getKey(1)))) {
790:                        it.remove();
791:                        modified = true;
792:                    }
793:                }
794:                return modified;
795:            }
796:
797:            /**
798:             * Removes all mappings where the first three keys are those specified.
799:             * <p>
800:             * This method removes all the mappings where the <code>MultiKey</code>
801:             * has three or more keys, and the first three match those specified.
802:             * 
803:             * @param key1  the first key
804:             * @param key2  the second key
805:             * @param key3  the third key
806:             * @return true if any elements were removed
807:             */
808:            public boolean removeAll(Object key1, Object key2, Object key3) {
809:                boolean modified = false;
810:                MapIterator it = mapIterator();
811:                while (it.hasNext()) {
812:                    MultiKey multi = (MultiKey) it.next();
813:                    if (multi.size() >= 3
814:                            && (key1 == null ? multi.getKey(0) == null : key1
815:                                    .equals(multi.getKey(0)))
816:                            && (key2 == null ? multi.getKey(1) == null : key2
817:                                    .equals(multi.getKey(1)))
818:                            && (key3 == null ? multi.getKey(2) == null : key3
819:                                    .equals(multi.getKey(2)))) {
820:                        it.remove();
821:                        modified = true;
822:                    }
823:                }
824:                return modified;
825:            }
826:
827:            /**
828:             * Removes all mappings where the first four keys are those specified.
829:             * <p>
830:             * This method removes all the mappings where the <code>MultiKey</code>
831:             * has four or more keys, and the first four match those specified.
832:             * 
833:             * @param key1  the first key
834:             * @param key2  the second key
835:             * @param key3  the third key
836:             * @param key4  the fourth key
837:             * @return true if any elements were removed
838:             */
839:            public boolean removeAll(Object key1, Object key2, Object key3,
840:                    Object key4) {
841:                boolean modified = false;
842:                MapIterator it = mapIterator();
843:                while (it.hasNext()) {
844:                    MultiKey multi = (MultiKey) it.next();
845:                    if (multi.size() >= 4
846:                            && (key1 == null ? multi.getKey(0) == null : key1
847:                                    .equals(multi.getKey(0)))
848:                            && (key2 == null ? multi.getKey(1) == null : key2
849:                                    .equals(multi.getKey(1)))
850:                            && (key3 == null ? multi.getKey(2) == null : key3
851:                                    .equals(multi.getKey(2)))
852:                            && (key4 == null ? multi.getKey(3) == null : key4
853:                                    .equals(multi.getKey(3)))) {
854:                        it.remove();
855:                        modified = true;
856:                    }
857:                }
858:                return modified;
859:            }
860:
861:            //-----------------------------------------------------------------------
862:            /**
863:             * Check to ensure that input keys are valid MultiKey objects.
864:             * 
865:             * @param key  the key to check
866:             */
867:            protected void checkKey(Object key) {
868:                if (key == null) {
869:                    throw new NullPointerException("Key must not be null");
870:                }
871:                if (key instanceof  MultiKey == false) {
872:                    throw new ClassCastException("Key must be a MultiKey");
873:                }
874:            }
875:
876:            /**
877:             * Clones the map without cloning the keys or values.
878:             *
879:             * @return a shallow clone
880:             */
881:            public Object clone() {
882:                return new MultiKeyMap((AbstractHashedMap) map.clone());
883:            }
884:
885:            /**
886:             * Puts the key and value into the map, where the key must be a non-null
887:             * MultiKey object.
888:             * 
889:             * @param key  the non-null MultiKey object
890:             * @param value  the value to store
891:             * @return the previous value for the key
892:             * @throws NullPointerException if the key is null
893:             * @throws ClassCastException if the key is not a MultiKey
894:             */
895:            public Object put(Object key, Object value) {
896:                checkKey(key);
897:                return map.put(key, value);
898:            }
899:
900:            /**
901:             * Copies all of the keys and values from the specified map to this map.
902:             * Each key must be non-null and a MultiKey object.
903:             * 
904:             * @param mapToCopy  to this map
905:             * @throws NullPointerException if the mapToCopy or any key within is null
906:             * @throws ClassCastException if any key in mapToCopy is not a MultiKey
907:             */
908:            public void putAll(Map mapToCopy) {
909:                for (Iterator it = mapToCopy.keySet().iterator(); it.hasNext();) {
910:                    Object key = it.next();
911:                    checkKey(key);
912:                }
913:                map.putAll(mapToCopy);
914:            }
915:
916:            //-----------------------------------------------------------------------
917:            public MapIterator mapIterator() {
918:                return map.mapIterator();
919:            }
920:
921:            public int size() {
922:                return map.size();
923:            }
924:
925:            public boolean isEmpty() {
926:                return map.isEmpty();
927:            }
928:
929:            public boolean containsKey(Object key) {
930:                return map.containsKey(key);
931:            }
932:
933:            public boolean containsValue(Object value) {
934:                return map.containsValue(value);
935:            }
936:
937:            public Object get(Object key) {
938:                return map.get(key);
939:            }
940:
941:            public Object remove(Object key) {
942:                return map.remove(key);
943:            }
944:
945:            public void clear() {
946:                map.clear();
947:            }
948:
949:            public Set keySet() {
950:                return map.keySet();
951:            }
952:
953:            public Collection values() {
954:                return map.values();
955:            }
956:
957:            public Set entrySet() {
958:                return map.entrySet();
959:            }
960:
961:            public boolean equals(Object obj) {
962:                if (obj == this ) {
963:                    return true;
964:                }
965:                return map.equals(obj);
966:            }
967:
968:            public int hashCode() {
969:                return map.hashCode();
970:            }
971:
972:            public String toString() {
973:                return map.toString();
974:            }
975:
976:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.