001: /* $Id: IntHashMap.java,v 1.2 2005/12/22 09:02:30 ahimanikya Exp $
002: * =======================================================================
003: * Copyright (c) 2005 Axion Development Team. All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions
007: * are met:
008: *
009: * 1. Redistributions of source code must retain the above
010: * copyright notice, this list of conditions and the following
011: * disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The names "Tigris", "Axion", nor the names of its contributors may
019: * not be used to endorse or promote products derived from this
020: * software without specific prior written permission.
021: *
022: * 4. Products derived from this software may not be called "Axion", nor
023: * may "Tigris" or "Axion" appear in their names without specific prior
024: * written permission.
025: *
026: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
027: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
028: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
029: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
030: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
031: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
032: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
033: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
034: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
035: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
036: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037: * =======================================================================
038: */
039: package org.axiondb.engine.rowcollection;
040:
041: import java.util.NoSuchElementException;
042:
043: import org.apache.commons.collections.primitives.IntCollection;
044: import org.apache.commons.collections.primitives.IntIterator;
045: import org.apache.commons.collections.primitives.IntListIterator;
046: import org.axiondb.RowCollection;
047:
048: /**
049: * Int key and Object value Map, this does not implement java.util.Map interface and has
050: * limited Map like API. Does not implement EntrySet and and KeySet, tather it just
051: * retunds their iterator.
052: *
053: * @version $Revision: 1.2 $ $Date: 2005/12/22 09:02:30 $
054: * @author Ahimanikya Satapathy
055: */
056:
057: public class IntHashMap {
058:
059: /** Creates an IntHashMap of small initial capacity. */
060: public IntHashMap() {
061: this (16);
062: }
063:
064: /**
065: * Creates an IntHashMap of specified initial capacity. Unless the map size exceeds the
066: * specified capacity no memory allocation is ever performed.
067: *
068: * @param capacity the initial capacity.
069: */
070: public IntHashMap(int capacity) {
071: int tableLength = 16;
072: while (tableLength < capacity) {
073: tableLength <<= 1;
074: }
075: _entries = new IntHashMap.Entry[tableLength];
076: _head._next = _tail;
077: _tail._previous = _head;
078: Entry previous = _tail;
079: for (int i = 0; i++ < capacity;) {
080: Entry newEntry = newEntry();
081: newEntry._previous = previous;
082: previous._next = newEntry;
083: previous = newEntry;
084: }
085: }
086:
087: /**
088: * Creates a IntHashMap containing the specified entries, in the order they are
089: * returned by the map's iterator.
090: *
091: * @param map the map whose entries are to be placed into this map.
092: */
093: public IntHashMap(IntHashMap map) {
094: this (map.size());
095: putAll(map);
096: }
097:
098: /**
099: * Removes all mappings from this {@link IntHashMap}.
100: */
101: public void clear() {
102: // Clears all keys, values and buckets linked lists.
103: for (Entry e = _head, end = _tail; (e = e._next) != end;) {
104: e._key = -1;
105: e._value = null;
106: final Entry[] table = e._table;
107: table[e._keyHash & (table.length - 1)] = null;
108: }
109: _tail = _head._next;
110: _size = 0;
111:
112: // Discards old entries.
113: _oldEntries = null;
114: }
115:
116: /**
117: * Indicates if this {@link IntHashMap}contains a mapping for the specified key.
118: *
119: * @param key the key whose presence in this map is to be tested.
120: * @return <code>true</code> if this map contains a mapping for the specified key;
121: * <code>false</code> otherwise.
122: */
123: public final boolean containsKey(int key) {
124: final int keyHash = key;
125: Entry entry = _entries[keyHash & (_entries.length - 1)];
126: while (entry != null) {
127: if ((key == entry._key)
128: || ((entry._keyHash == keyHash) && (key == entry._key))) {
129: return true;
130: }
131: entry = entry._beside;
132: }
133: return (_oldEntries != null) ? _oldEntries.containsKey(key)
134: : false;
135: }
136:
137: /**
138: * Indicates if this {@link IntHashMap}maps one or more keys to the specified value.
139: *
140: * @param value the value whose presence in this map is to be tested.
141: * @return <code>true</code> if this map maps one or more keys to the specified
142: * value.
143: */
144: public final boolean containsValue(Object value) {
145: for (Entry e = headEntry(), end = tailEntry(); (e = e._next) != end;) {
146: if (value.equals(e._value)) {
147: return true;
148: }
149: }
150: return false;
151: }
152:
153: public EntryIterator entryIterator() {
154: return new EntryIterator();
155: }
156:
157: /**
158: * Compares the specified object with this {@link IntHashMap}for equality. Returns
159: * <code>true</code> if the given object is also a map and the two maps represent
160: * the same mappings (regardless of collection iteration order).
161: *
162: * @param obj the object to be compared for equality with this map.
163: * @return <code>true</code> if the specified object is equal to this map;
164: * <code>false</code> otherwise.
165: */
166: public boolean equals(Object obj) {
167: if (obj == this ) {
168: return true;
169: } else if (obj instanceof IntHashMap) {
170: IntHashMap that = (IntHashMap) obj;
171: if (this ._size == that._size) {
172: for (Entry e = _head, end = _tail; (e = e._next) != end;) {
173: if (!that.containsKey(e._key)) {
174: return false;
175: }
176: }
177: return true;
178: } else {
179: return false;
180: }
181: } else {
182: return false;
183: }
184: }
185:
186: /**
187: * Returns the value to which this {@link IntHashMap}maps the specified key.
188: *
189: * @param key the key whose associated value is to be returned.
190: * @return the value to which this map maps the specified key, or <code>null</code>
191: * if there is no mapping for the key.
192: */
193: public final Object get(int key) {
194: final int keyHash = key;
195: Entry entry = _entries[keyHash & (_entries.length - 1)];
196: while (entry != null) {
197: if ((key == entry._key)
198: || ((entry._keyHash == keyHash) && (key == entry._key))) {
199: return entry._value;
200: }
201: entry = entry._beside;
202: }
203: return (_oldEntries != null) ? _oldEntries.get(key) : null;
204: }
205:
206: /**
207: * Returns the entry with the specified key.
208: *
209: * @param key the key whose associated entry is to be returned.
210: * @return the entry for the specified key or <code>null</code> if none.
211: */
212: public final Entry getEntry(int key) {
213: final int keyHash = key;
214: Entry entry = _entries[keyHash & (_entries.length - 1)];
215: while (entry != null) {
216: if ((key == entry._key)
217: || ((entry._keyHash == keyHash) && (key == entry._key))) {
218: return entry;
219: }
220: entry = entry._beside;
221: }
222: return (_oldEntries != null) ? _oldEntries.getEntry(key) : null;
223: }
224:
225: /**
226: * Returns the hash code value for this {@link IntHashMap}.
227: *
228: * @return the hash code value for this map.
229: */
230: public int hashCode() {
231: int code = 0;
232: for (Entry e = _head, end = _tail; (e = e._next) != end;) {
233: code += e.hashCode();
234: }
235: return code;
236: }
237:
238: /**
239: * Returns the head entry of this map.
240: *
241: * @return the entry such as <code>headEntry().getNextEntry()</code> holds the first
242: * map entry.
243: */
244: public final Entry headEntry() {
245: return _head;
246: }
247:
248: /**
249: * Indicates if this {@link IntHashMap}contains no key-value mappings.
250: *
251: * @return <code>true</code> if this map contains no key-value mappings;
252: * <code>false</code> otherwise.
253: */
254: public final boolean isEmpty() {
255: return _head._next == _tail;
256: }
257:
258: public IntListIterator keyIterator() {
259: return new IntKeyIterator();
260: }
261:
262: /**
263: * Associates the specified value with the specified key in this {@link IntHashMap}.
264: * If the {@link IntHashMap}previously contained a mapping for this key, the old value
265: * is replaced.
266: *
267: * @param key the key with which the specified value is to be associated.
268: * @param value the value to be associated with the specified key.
269: * @return the previous value associated with specified key, or <code>null</code> if
270: * there was no mapping for key. A <code>null</code> return can also
271: * indicate that the map previously associated <code>null</code> with the
272: * specified key.
273: */
274: public final Object put(int key, Object value) {
275: final int keyHash = key;
276: Entry entry = _entries[keyHash & (_entries.length - 1)];
277: while (entry != null) {
278: if ((key == entry._key)
279: || ((entry._keyHash == keyHash) && (key == entry._key))) {
280: Object prevValue = entry._value;
281: entry._value = value;
282: return prevValue;
283: }
284: entry = entry._beside;
285: }
286: // No mapping in current map, checks old one.
287: if (_oldEntries != null) {
288: // For safe unsynchronized access we don't remove old key.
289: if (_oldEntries.containsKey(key)) {
290: return _oldEntries.put(key, value);
291: }
292: }
293:
294: // The key is not mapped.
295: addEntry(keyHash, key, value);
296: return null;
297: }
298:
299: /**
300: * Copies all of the mappings from the specified map to this {@link IntHashMap}.
301: *
302: * @param map the mappings to be stored in this map.
303: */
304: public final void putAll(IntHashMap that) {
305: for (Entry e = that._head, end = that._tail; (e = e._next) != end;) {
306: put(e._key, e._value);
307: }
308: }
309:
310: /**
311: * Removes the mapping for this key from this {@link IntHashMap}if present.
312: *
313: * @param key the key whose mapping is to be removed from the map.
314: * @return previous value associated with specified key, or <code>null</code> if
315: * there was no mapping for key. A <code>null</code> return can also
316: * indicate that the map previously associated <code>null</code> with the
317: * specified key.
318: */
319: public final Object remove(int key) {
320: final int keyHash = key;
321: Entry entry = _entries[keyHash & (_entries.length - 1)];
322: while (entry != null) {
323: if ((key == entry._key)
324: || ((entry._keyHash == keyHash) && (key == entry._key))) {
325: Object prevValue = entry._value;
326: removeEntry(entry);
327: return prevValue;
328: }
329: entry = entry._beside;
330: }
331: // No mapping in current map.
332: if ((_oldEntries != null) && _oldEntries.containsKey(key)) {
333: _size--;
334: _oldEntries._tail = _tail; // Specifies the tail for entry storage.
335: return _oldEntries.remove(key);
336: }
337: return null;
338: }
339:
340: /**
341: * Removes the specified entry from the map.
342: *
343: * @param entry the entry to be removed.
344: */
345: public void removeEntry(Entry entry) {
346: // Updates size.
347: _size--;
348:
349: // Clears value and key.
350: entry._key = -1;
351: entry._value = null;
352:
353: // Detaches from map.
354: entry.detach();
355:
356: // Re-inserts next tail.
357: final Entry next = _tail._next;
358: entry._previous = _tail;
359: entry._next = next;
360: _tail._next = entry;
361: if (next != null) {
362: next._previous = entry;
363: }
364: }
365:
366: /**
367: * Returns a list iterator over the values in this list in proper sequence, (this map
368: * maintains the insertion order).
369: *
370: * @return a list iterator of the values in this list (in proper sequence).
371: */
372: public final ValueIterator valueIterator() {
373: return new ValueIterator();
374: }
375:
376: /**
377: * Returns the number of key-value mappings in this {@link IntHashMap}.
378: *
379: * @return this map's size.
380: */
381: public final int size() {
382: return _size;
383: }
384:
385: /**
386: * Returns the tail entry of this map.
387: *
388: * @return the entry such as <code>tailEntry().getPreviousEntry()</code> holds the
389: * last map entry.
390: */
391: public final Entry tailEntry() {
392: return _tail;
393: }
394:
395: /**
396: * Returns the textual representation of this {@link IntHashMap}.
397: *
398: * @return the textual representation of the entry set.
399: */
400: public String toString() {
401: return _entries.toString();
402: }
403:
404: /**
405: * Returns a {@link RowCollection}view of the values contained in this
406: * {@link IntHashMap}. The collection is backed by the map, so changes to the map are
407: * reflected in the collection, and vice-versa. The collection supports element
408: * removal, which removes the corresponding mapping from this map, via the
409: * <code>RowIterator.remove</code>,<code>RowCollection.remove</code> and
410: * <code>clear</code> operations.
411: *
412: * @return a row collection view of the values contained in this map.
413: */
414: public final Values values() {
415: return _values;
416: }
417:
418: public IntCollection keys() {
419: return _keys;
420: }
421:
422: /**
423: * Returns a new entry for this map; sub-classes may override this method to use
424: * custom entries.
425: *
426: * @return a new entry potentially preallocated.
427: */
428: protected Entry newEntry() {
429: return new Entry();
430: }
431:
432: /**
433: * Adds a new entry for the specified key and value.
434: *
435: * @param hash the hash of the key, generated with {@link #keyHash}.
436: * @param key the entry's key.
437: * @param value the entry's value.
438: */
439: protected void addEntry(int hash, int key, Object value) {
440: // Updates size.
441: if (_size++ > _entries.length) { // Check if entry table too small.
442: increaseEntryTable();
443: }
444:
445: Entry newTail = _tail._next;
446: if (newTail == null) {
447: newTail = _tail._next = newEntry();
448: newTail._previous = _tail;
449: }
450: // Setups entry parameters.
451: _tail._key = key;
452: _tail._value = value;
453: _tail._keyHash = hash;
454: _tail._table = _entries;
455:
456: // Connects to bucket.
457: final int index = hash & (_entries.length - 1);
458: Entry beside = _entries[index];
459: _tail._beside = beside;
460: _entries[index] = _tail; // Volatile.
461:
462: // Moves tail forward.
463: _tail = newTail;
464: }
465:
466: private void increaseEntryTable() {
467: int minLength = _entries.length << 1;
468: IntHashMap oldEntries;
469: oldEntries = new IntHashMap(1 << 6);
470: if (minLength <= (1 << 6)) { // 64
471: oldEntries = new IntHashMap(1 << 6);
472: } else if (minLength <= (1 << 8)) { // 256
473: oldEntries = new IntHashMap(1 << 8);
474: } else if (minLength <= (1 << 10)) { // 1,024
475: oldEntries = new IntHashMap(1 << 10);
476: } else if (minLength <= (1 << 14)) { // 16,384
477: oldEntries = new IntHashMap(1 << 14);
478: } else if (minLength <= (1 << 18)) { // 262,144
479: oldEntries = new IntHashMap(1 << 18);
480: } else if (minLength <= (1 << 22)) { // 4,194,304
481: oldEntries = new IntHashMap(1 << 22);
482: } else if (minLength <= (1 << 26)) { // 67,108,864
483: oldEntries = new IntHashMap(1 << 26);
484: } else { // 1,073,741,824
485: oldEntries = new IntHashMap(1 << 30);
486: }
487: // Swaps entries.
488: Entry[] newEntries = oldEntries._entries;
489: oldEntries._entries = _entries;
490: _entries = newEntries;
491:
492: // Setup the oldEntries map (used only for hash access).
493: oldEntries._oldEntries = _oldEntries;
494: oldEntries._head = null;
495: oldEntries._tail = null;
496: oldEntries._size = -1;
497:
498: // Done. We have now a much larger entry table.
499: // Still, we keep reference to the old entries through oldEntries
500: // until the map is cleared.
501: _oldEntries = oldEntries;
502: }
503:
504: /**
505: * This class represents a {@link IntHashMap}entry.
506: */
507: public static class Entry {
508:
509: /** Holds the next entry in the same bucket. */
510: private Entry _beside;
511:
512: /** Holds the entry key. */
513: private int _key;
514:
515: /** Holds the key hash code. */
516: private int _keyHash;
517:
518: /** Holds the next node. */
519: private Entry _next;
520:
521: /** Holds the previous node. */
522: private Entry _previous;
523:
524: /** Holds the hash table this entry belongs to. */
525: private Entry[] _table;
526:
527: /** Holds the entry value. */
528: private Object _value;
529:
530: /** Default constructor (allows sub-classing). */
531: protected Entry() {
532: }
533:
534: /**
535: * Indicates if this entry is considered equals to the specified entry (default
536: * object equality to ensure symetry)
537: *
538: * @param that the object to test for equality.
539: * @return <code>true<code> if both entry have equal keys and values.
540: * <code>false<code> otherwise.
541: */
542: public boolean equals(Object that) {
543: if (that instanceof Entry) {
544: Entry entry = (Entry) that;
545: return (_key == getKey())
546: && ((_value != null) ? _value.equals(entry
547: .getValue())
548: : (entry.getValue() == null));
549: } else {
550: return false;
551: }
552: }
553:
554: /**
555: * Returns the key for this entry.
556: *
557: * @return the entry key.
558: */
559: public final int getKey() {
560: return _key;
561: }
562:
563: /**
564: * Returns the entry after this one.
565: *
566: * @return the next entry.
567: */
568: public Entry getNextEntry() {
569: return _next;
570: }
571:
572: /**
573: * Returns the entry before this one.
574: *
575: * @return the previous entry.
576: */
577: public Entry getPreviousEntry() {
578: return _previous;
579: }
580:
581: /**
582: * Returns the value for this entry.
583: *
584: * @return the entry value.
585: */
586: public final Object getValue() {
587: return _value;
588: }
589:
590: /**
591: * Returns the hash code for this entry.
592: *
593: * @return this entry hash code.
594: */
595: public int hashCode() {
596: return _key ^ ((_value != null) ? _value.hashCode() : 0);
597: }
598:
599: /**
600: * Sets the value for this entry.
601: *
602: * @param value the new value.
603: * @return the previous value.
604: */
605: public final Object setValue(Object value) {
606: Object old = _value;
607: _value = value;
608: return old;
609: }
610:
611: /**
612: * Detaches this entry from the entry table and list.
613: */
614: private void detach() {
615: // Removes from list.
616: _previous._next = _next;
617: _next._previous = _previous;
618:
619: // Removes from bucket.
620: final int index = _keyHash & (_table.length - 1);
621: final Entry beside = _beside;
622: Entry previous = _table[index];
623: if (previous == this ) { // First in bucket.
624: _table[index] = beside;
625: } else {
626: while (previous._beside != this ) {
627: previous = previous._beside;
628: }
629: previous._beside = beside;
630: }
631: }
632: }
633:
634: public class EntryIterator {
635:
636: private int _currentIndex;
637: private Entry _currentNode;
638: private int _nextIndex;
639: private Entry _nextNode;
640:
641: public EntryIterator() {
642: _nextNode = _head._next;
643: _currentNode = null;
644: _nextIndex = 0;
645: _currentIndex = -1;
646: }
647:
648: public void addEntry(int hash, int key, Object value) {
649: IntHashMap.this .addEntry(hash, key, value);
650: _currentNode = null;
651: _nextIndex++;
652: _currentIndex = -1;
653: }
654:
655: public Entry currentEntry() {
656: if (!hasCurrent())
657: throw new NoSuchElementException();
658: return _currentNode;
659: }
660:
661: public int currentIndex() {
662: return _currentIndex;
663: }
664:
665: public Entry firstEntry() {
666: reset();
667: return peekNextEntry();
668: }
669:
670: public boolean hasCurrent() {
671: return (_currentNode != null);
672: }
673:
674: public boolean hasNext() {
675: return (_nextIndex < IntHashMap.this ._size);
676: }
677:
678: public boolean hasPrevious() {
679: return _nextIndex > 0;
680: }
681:
682: public boolean isEmpty() {
683: return IntHashMap.this .isEmpty();
684: }
685:
686: public Entry lastEntry() {
687: if (!hasNext()) {
688: previousEntry();
689: }
690: Entry entry = null;
691: while (hasNext()) {
692: entry = nextEntry();
693: }
694: return entry;
695: }
696:
697: public Entry nextEntry() {
698: if (_nextIndex == IntHashMap.this ._size)
699: throw new NoSuchElementException();
700: _currentIndex = _nextIndex;
701: _nextIndex++;
702: _currentNode = _nextNode;
703: _nextNode = _nextNode._next;
704: return _currentNode;
705: }
706:
707: public int nextIndex() {
708: return _nextIndex;
709: }
710:
711: public Entry peekNextEntry() {
712: nextEntry();
713: return previousEntry();
714: }
715:
716: public Entry peekPreviousEntry() {
717: previousEntry();
718: return nextEntry();
719: }
720:
721: public Entry previousEntry() {
722: if (_nextIndex == 0)
723: throw new NoSuchElementException();
724: _nextIndex--;
725: _currentIndex = _nextIndex;
726: _currentNode = _nextNode = _nextNode._previous;
727: return _currentNode;
728: }
729:
730: public int previousIndex() {
731: return _nextIndex - 1;
732: }
733:
734: public void remove() {
735: if (_currentNode != null) {
736: if (_nextNode == _currentNode) { // previous() has been called.
737: _nextNode = _nextNode._next;
738: } else {
739: _nextIndex--;
740: }
741: IntHashMap.this .removeEntry(_currentNode);
742: _currentNode = null;
743: _currentIndex = -1;
744: } else {
745: throw new IllegalStateException();
746: }
747: }
748:
749: public void reset() {
750: _nextNode = _head._next;
751: _currentNode = null;
752: _nextIndex = 0;
753: _currentIndex = -1;
754: }
755:
756: public void setEntry(Entry o) {
757: if (_currentNode != null) {
758: _currentNode = o;
759: } else {
760: throw new IllegalStateException();
761: }
762: }
763:
764: public int size() {
765: return IntHashMap.this ._size;
766: }
767: }
768:
769: private class IntKeyIterator extends EntryIterator implements
770: IntListIterator {
771: public int next() {
772: return nextEntry().getKey();
773: }
774:
775: public void add(int element) {
776: throw new UnsupportedOperationException();
777: }
778:
779: public int previous() {
780: return previousEntry().getKey();
781: }
782:
783: public void set(int element) {
784: throw new UnsupportedOperationException();
785: }
786: }
787:
788: public class ValueIterator extends EntryIterator {
789:
790: public void add(Object row)
791: throws UnsupportedOperationException {
792: throw new UnsupportedOperationException();
793: }
794:
795: public Object current() throws NoSuchElementException {
796: return currentEntry().getValue();
797: }
798:
799: public Object first() throws NoSuchElementException {
800: return firstEntry().getValue();
801: }
802:
803: public Object last() throws NoSuchElementException {
804: return lastEntry().getValue();
805: }
806:
807: public Object next() throws NoSuchElementException {
808: return nextEntry().getValue();
809: }
810:
811: public Object peekNext() throws NoSuchElementException {
812: return peekNextEntry().getValue();
813: }
814:
815: public Object peekPrevious() throws NoSuchElementException {
816: return peekPreviousEntry().getValue();
817: }
818:
819: public Object previous() throws NoSuchElementException {
820: return previousEntry().getValue();
821: }
822:
823: public void set(Object row)
824: throws UnsupportedOperationException {
825: if (!hasCurrent()) {
826: throw new IllegalStateException();
827: }
828: currentEntry().setValue(row);
829: }
830:
831: public int next(int count) {
832: for (int i = 0; i < count; i++) {
833: next();
834: }
835: return currentEntry().getKey();
836: }
837:
838: public int previous(int count) {
839: for (int i = 0; i < count; i++) {
840: previous();
841: }
842: return currentEntry().getKey();
843: }
844:
845: }
846:
847: private class Keys implements IntCollection {
848:
849: public boolean add(int id) {
850: throw new UnsupportedOperationException();
851: }
852:
853: public void clear() {
854: IntHashMap.this .clear();
855: }
856:
857: public boolean contains(int id) {
858: return IntHashMap.this .containsKey(id);
859: }
860:
861: public boolean isEmpty() {
862: return IntHashMap.this .isEmpty();
863: }
864:
865: public IntIterator iterator() {
866: return IntHashMap.this .keyIterator();
867: }
868:
869: public boolean remove(int id) {
870: return IntHashMap.this .remove(id) != null;
871: }
872:
873: public int size() {
874: return IntHashMap.this .size();
875: }
876:
877: public boolean addAll(IntCollection c) {
878: throw new UnsupportedOperationException();
879: }
880:
881: public boolean containsAll(IntCollection c) {
882: throw new UnsupportedOperationException();
883: }
884:
885: public boolean removeAll(IntCollection c) {
886: throw new UnsupportedOperationException();
887: }
888:
889: public boolean removeElement(int element) {
890: return IntHashMap.this .remove(element) != null;
891: }
892:
893: public boolean retainAll(IntCollection c) {
894: throw new UnsupportedOperationException();
895: }
896:
897: public int[] toArray() {
898: throw new UnsupportedOperationException();
899: }
900:
901: public int[] toArray(int[] a) {
902: throw new UnsupportedOperationException();
903: }
904: }
905:
906: protected class Values {
907:
908: public boolean add(Object row) {
909: throw new UnsupportedOperationException();
910: }
911:
912: public void clear() {
913: IntHashMap.this .clear();
914: }
915:
916: public ValueIterator iterator() {
917: return valueIterator();
918: }
919:
920: public int size() {
921: return _size;
922: }
923:
924: public boolean contains(Object row) {
925: return IntHashMap.this .containsValue(row);
926: }
927:
928: public boolean isEmpty() {
929: return IntHashMap.this .isEmpty();
930: }
931:
932: public boolean remove(Object row) {
933: for (Entry r = headEntry(), end = tailEntry(); (r = r._next) != end;) {
934: if (row.equals(r._value)) {
935: IntHashMap.this .removeEntry(r);
936: return true;
937: }
938: }
939: return false;
940: }
941: }
942:
943: /** Holds the map's hash table (volatile for unsynchronized access). */
944: private volatile transient Entry[] _entries;
945:
946: /**
947: * Holds the head entry to which the first entry attaches. The head entry never
948: * changes (entries always added last).
949: */
950: private transient Entry _head = newEntry();
951:
952: /** Holds a reference to a map having the old entries when resizing. */
953: private transient IntHashMap _oldEntries;
954:
955: /** Holds the current size. */
956: private transient int _size;
957:
958: /**
959: * Holds the tail entry to which the last entry attaches. The tail entry changes as
960: * entries are added/removed.
961: */
962: private transient Entry _tail = newEntry();
963:
964: /** Holds the values view. */
965: private transient Values _values = new Values();
966:
967: /** Holds the keys view. */
968: private transient Keys _keys = new Keys();
969: }
|