IntHashMap.java :  » Database-DBMS » axion » org » axiondb » engine » rowcollection » Java Open Source

Java Open Source » Database DBMS » axion 
axion » org » axiondb » engine » rowcollection » IntHashMap.java
/* $Id: IntHashMap.java,v 1.2 2005/12/22 09:02:30 ahimanikya Exp $
 * =======================================================================
 * Copyright (c) 2005 Axion Development Team.  All rights reserved.
 *  
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * 
 * 1. Redistributions of source code must retain the above 
 *    copyright notice, this list of conditions and the following 
 *    disclaimer. 
 *   
 * 2. Redistributions in binary form must reproduce the above copyright 
 *    notice, this list of conditions and the following disclaimer in 
 *    the documentation and/or other materials provided with the 
 *    distribution. 
 *   
 * 3. The names "Tigris", "Axion", nor the names of its contributors may 
 *    not be used to endorse or promote products derived from this 
 *    software without specific prior written permission. 
 *  
 * 4. Products derived from this software may not be called "Axion", nor 
 *    may "Tigris" or "Axion" appear in their names without specific prior
 *    written permission.
 *   
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * =======================================================================
 */
package org.axiondb.engine.rowcollection;

import java.util.NoSuchElementException;

import org.apache.commons.collections.primitives.IntCollection;
import org.apache.commons.collections.primitives.IntIterator;
import org.apache.commons.collections.primitives.IntListIterator;
import org.axiondb.RowCollection;

/**
 * Int key and Object value Map, this does not implement java.util.Map interface and has
 * limited Map like API. Does not implement EntrySet and and KeySet, tather it just
 * retunds their iterator.
 * 
 * @version $Revision: 1.2 $ $Date: 2005/12/22 09:02:30 $
 * @author Ahimanikya Satapathy
 */

public class IntHashMap {

    /** Creates an IntHashMap of small initial capacity. */
    public IntHashMap() {
        this(16);
    }

    /**
     * Creates an IntHashMap of specified initial capacity. Unless the map size exceeds the
     * specified capacity no memory allocation is ever performed.
     * 
     * @param capacity the initial capacity.
     */
    public IntHashMap(int capacity) {
        int tableLength = 16;
        while (tableLength < capacity) {
            tableLength <<= 1;
        }
        _entries = new IntHashMap.Entry[tableLength];
        _head._next = _tail;
        _tail._previous = _head;
        Entry previous = _tail;
        for (int i = 0; i++ < capacity;) {
            Entry newEntry = newEntry();
            newEntry._previous = previous;
            previous._next = newEntry;
            previous = newEntry;
        }
    }

    /**
     * Creates a IntHashMap containing the specified entries, in the order they are
     * returned by the map's iterator.
     * 
     * @param map the map whose entries are to be placed into this map.
     */
    public IntHashMap(IntHashMap map) {
        this(map.size());
        putAll(map);
    }

    /**
     * Removes all mappings from this {@link IntHashMap}.
     */
    public void clear() {
        // Clears all keys, values and buckets linked lists.
        for (Entry e = _head, end = _tail; (e = e._next) != end;) {
            e._key = -1;
            e._value = null;
            final Entry[] table = e._table;
            table[e._keyHash & (table.length - 1)] = null;
        }
        _tail = _head._next;
        _size = 0;

        // Discards old entries.
        _oldEntries = null;
    }

    /**
     * Indicates if this {@link IntHashMap}contains a mapping for the specified key.
     * 
     * @param key the key whose presence in this map is to be tested.
     * @return <code>true</code> if this map contains a mapping for the specified key;
     *         <code>false</code> otherwise.
     */
    public final boolean containsKey(int key) {
        final int keyHash = key;
        Entry entry = _entries[keyHash & (_entries.length - 1)];
        while (entry != null) {
            if ((key == entry._key) || ((entry._keyHash == keyHash) && (key == entry._key))) {
                return true;
            }
            entry = entry._beside;
        }
        return (_oldEntries != null) ? _oldEntries.containsKey(key) : false;
    }

    /**
     * Indicates if this {@link IntHashMap}maps one or more keys to the specified value.
     * 
     * @param value the value whose presence in this map is to be tested.
     * @return <code>true</code> if this map maps one or more keys to the specified
     *         value.
     */
    public final boolean containsValue(Object value) {
        for (Entry e = headEntry(), end = tailEntry(); (e = e._next) != end;) {
            if (value.equals(e._value)) {
                return true;
            }
        }
        return false;
    }

    public EntryIterator entryIterator() {
        return new EntryIterator();
    }

    /**
     * Compares the specified object with this {@link IntHashMap}for equality. Returns
     * <code>true</code> if the given object is also a map and the two maps represent
     * the same mappings (regardless of collection iteration order).
     * 
     * @param obj the object to be compared for equality with this map.
     * @return <code>true</code> if the specified object is equal to this map;
     *         <code>false</code> otherwise.
     */
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        } else if (obj instanceof IntHashMap) {
            IntHashMap that = (IntHashMap) obj;
            if (this._size == that._size) {
                for (Entry e = _head, end = _tail; (e = e._next) != end;) {
                    if (!that.containsKey(e._key)) {
                        return false;
                    }
                }
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * Returns the value to which this {@link IntHashMap}maps the specified key.
     * 
     * @param key the key whose associated value is to be returned.
     * @return the value to which this map maps the specified key, or <code>null</code>
     *         if there is no mapping for the key.
     */
    public final Object get(int key) {
        final int keyHash = key;
        Entry entry = _entries[keyHash & (_entries.length - 1)];
        while (entry != null) {
            if ((key == entry._key) || ((entry._keyHash == keyHash) && (key == entry._key))) {
                return entry._value;
            }
            entry = entry._beside;
        }
        return (_oldEntries != null) ? _oldEntries.get(key) : null;
    }

    /**
     * Returns the entry with the specified key.
     * 
     * @param key the key whose associated entry is to be returned.
     * @return the entry for the specified key or <code>null</code> if none.
     */
    public final Entry getEntry(int key) {
        final int keyHash = key;
        Entry entry = _entries[keyHash & (_entries.length - 1)];
        while (entry != null) {
            if ((key == entry._key) || ((entry._keyHash == keyHash) && (key == entry._key))) {
                return entry;
            }
            entry = entry._beside;
        }
        return (_oldEntries != null) ? _oldEntries.getEntry(key) : null;
    }

    /**
     * Returns the hash code value for this {@link IntHashMap}.
     * 
     * @return the hash code value for this map.
     */
    public int hashCode() {
        int code = 0;
        for (Entry e = _head, end = _tail; (e = e._next) != end;) {
            code += e.hashCode();
        }
        return code;
    }

    /**
     * Returns the head entry of this map.
     * 
     * @return the entry such as <code>headEntry().getNextEntry()</code> holds the first
     *         map entry.
     */
    public final Entry headEntry() {
        return _head;
    }

    /**
     * Indicates if this {@link IntHashMap}contains no key-value mappings.
     * 
     * @return <code>true</code> if this map contains no key-value mappings;
     *         <code>false</code> otherwise.
     */
    public final boolean isEmpty() {
        return _head._next == _tail;
    }

    public IntListIterator keyIterator() {
        return new IntKeyIterator();
    }

    /**
     * Associates the specified value with the specified key in this {@link IntHashMap}.
     * If the {@link IntHashMap}previously contained a mapping for this key, the old value
     * is replaced.
     * 
     * @param key the key with which the specified value is to be associated.
     * @param value the value to be associated with the specified key.
     * @return the previous value associated with specified key, or <code>null</code> if
     *         there was no mapping for key. A <code>null</code> return can also
     *         indicate that the map previously associated <code>null</code> with the
     *         specified key.
     */
    public final Object put(int key, Object value) {
        final int keyHash = key;
        Entry entry = _entries[keyHash & (_entries.length - 1)];
        while (entry != null) {
            if ((key == entry._key) || ((entry._keyHash == keyHash) && (key == entry._key))) {
                Object prevValue = entry._value;
                entry._value = value;
                return prevValue;
            }
            entry = entry._beside;
        }
        // No mapping in current map, checks old one.
        if (_oldEntries != null) {
            // For safe unsynchronized access we don't remove old key.
            if (_oldEntries.containsKey(key)) {
                return _oldEntries.put(key, value);
            }
        }

        // The key is not mapped.
        addEntry(keyHash, key, value);
        return null;
    }

    /**
     * Copies all of the mappings from the specified map to this {@link IntHashMap}.
     * 
     * @param map the mappings to be stored in this map.
     */
    public final void putAll(IntHashMap that) {
        for (Entry e = that._head, end = that._tail; (e = e._next) != end;) {
            put(e._key, e._value);
        }
    }

    /**
     * Removes the mapping for this key from this {@link IntHashMap}if present.
     * 
     * @param key the key whose mapping is to be removed from the map.
     * @return previous value associated with specified key, or <code>null</code> if
     *         there was no mapping for key. A <code>null</code> return can also
     *         indicate that the map previously associated <code>null</code> with the
     *         specified key.
     */
    public final Object remove(int key) {
        final int keyHash = key;
        Entry entry = _entries[keyHash & (_entries.length - 1)];
        while (entry != null) {
            if ((key == entry._key) || ((entry._keyHash == keyHash) && (key == entry._key))) {
                Object prevValue = entry._value;
                removeEntry(entry);
                return prevValue;
            }
            entry = entry._beside;
        }
        // No mapping in current map.
        if ((_oldEntries != null) && _oldEntries.containsKey(key)) {
            _size--;
            _oldEntries._tail = _tail; // Specifies the tail for entry storage.
            return _oldEntries.remove(key);
        }
        return null;
    }

    /**
     * Removes the specified entry from the map.
     * 
     * @param entry the entry to be removed.
     */
    public void removeEntry(Entry entry) {
        // Updates size.
        _size--;

        // Clears value and key.
        entry._key = -1;
        entry._value = null;

        // Detaches from map.
        entry.detach();

        // Re-inserts next tail.
        final Entry next = _tail._next;
        entry._previous = _tail;
        entry._next = next;
        _tail._next = entry;
        if (next != null) {
            next._previous = entry;
        }
    }

    /**
     * Returns a list iterator over the values in this list in proper sequence, (this map
     * maintains the insertion order).
     * 
     * @return a list iterator of the values in this list (in proper sequence).
     */
    public final ValueIterator valueIterator() {
        return new ValueIterator();
    }

    /**
     * Returns the number of key-value mappings in this {@link IntHashMap}.
     * 
     * @return this map's size.
     */
    public final int size() {
        return _size;
    }

    /**
     * Returns the tail entry of this map.
     * 
     * @return the entry such as <code>tailEntry().getPreviousEntry()</code> holds the
     *         last map entry.
     */
    public final Entry tailEntry() {
        return _tail;
    }

    /**
     * Returns the textual representation of this {@link IntHashMap}.
     * 
     * @return the textual representation of the entry set.
     */
    public String toString() {
        return _entries.toString();
    }

    /**
     * Returns a {@link RowCollection}view of the values contained in this
     * {@link IntHashMap}. The collection is backed by the map, so changes to the map are
     * reflected in the collection, and vice-versa. The collection supports element
     * removal, which removes the corresponding mapping from this map, via the
     * <code>RowIterator.remove</code>,<code>RowCollection.remove</code> and
     * <code>clear</code> operations.
     * 
     * @return a row collection view of the values contained in this map.
     */
    public final Values values() {
        return _values;
    }
    
    public IntCollection keys() {
        return _keys;
    }

    /**
     * Returns a new entry for this map; sub-classes may override this method to use
     * custom entries.
     * 
     * @return a new entry potentially preallocated.
     */
    protected Entry newEntry() {
        return new Entry();
    }

    /**
     * Adds a new entry for the specified key and value.
     * 
     * @param hash the hash of the key, generated with {@link #keyHash}.
     * @param key the entry's key.
     * @param value the entry's value.
     */
    protected void addEntry(int hash, int key, Object value) {
        // Updates size.
        if (_size++ > _entries.length) { // Check if entry table too small.
            increaseEntryTable();
        }

        Entry newTail = _tail._next;
        if (newTail == null) {
            newTail = _tail._next = newEntry();
            newTail._previous = _tail;
        }
        // Setups entry parameters.
        _tail._key = key;
        _tail._value = value;
        _tail._keyHash = hash;
        _tail._table = _entries;

        // Connects to bucket.
        final int index = hash & (_entries.length - 1);
        Entry beside = _entries[index];
        _tail._beside = beside;
        _entries[index] = _tail; // Volatile.

        // Moves tail forward.
        _tail = newTail;
    }

    private void increaseEntryTable() {
        int minLength = _entries.length << 1;
        IntHashMap oldEntries;
        oldEntries = new IntHashMap(1 << 6);
        if (minLength <= (1 << 6)) { // 64
            oldEntries = new IntHashMap(1 << 6);
        } else if (minLength <= (1 << 8)) { // 256
            oldEntries = new IntHashMap(1 << 8);
        } else if (minLength <= (1 << 10)) { // 1,024
            oldEntries = new IntHashMap(1 << 10);
        } else if (minLength <= (1 << 14)) { // 16,384
            oldEntries = new IntHashMap(1 << 14);
        } else if (minLength <= (1 << 18)) { // 262,144
            oldEntries = new IntHashMap(1 << 18);
        } else if (minLength <= (1 << 22)) { // 4,194,304
            oldEntries = new IntHashMap(1 << 22);
        } else if (minLength <= (1 << 26)) { // 67,108,864
            oldEntries = new IntHashMap(1 << 26);
        } else { // 1,073,741,824
            oldEntries = new IntHashMap(1 << 30);
        }
        // Swaps entries.
        Entry[] newEntries = oldEntries._entries;
        oldEntries._entries = _entries;
        _entries = newEntries;

        // Setup the oldEntries map (used only for hash access).
        oldEntries._oldEntries = _oldEntries;
        oldEntries._head = null;
        oldEntries._tail = null;
        oldEntries._size = -1;

        // Done. We have now a much larger entry table.
        // Still, we keep reference to the old entries through oldEntries
        // until the map is cleared.
        _oldEntries = oldEntries;
    }

    /**
     * This class represents a {@link IntHashMap}entry.
     */
    public static class Entry {

        /** Holds the next entry in the same bucket. */
        private Entry _beside;

        /** Holds the entry key. */
        private int _key;

        /** Holds the key hash code. */
        private int _keyHash;

        /** Holds the next node. */
        private Entry _next;

        /** Holds the previous node. */
        private Entry _previous;

        /** Holds the hash table this entry belongs to. */
        private Entry[] _table;

        /** Holds the entry value. */
        private Object _value;

        /** Default constructor (allows sub-classing). */
        protected Entry() {
        }

        /**
         * Indicates if this entry is considered equals to the specified entry (default
         * object equality to ensure symetry)
         * 
         * @param that the object to test for equality.
         * @return <code>true<code> if both entry have equal keys and values.
         *         <code>false<code> otherwise.
         */
        public boolean equals(Object that) {
            if (that instanceof Entry) {
                Entry entry = (Entry) that;
                return (_key == getKey()) && ((_value != null) ? _value.equals(entry.getValue()) : (entry.getValue() == null));
            } else {
                return false;
            }
        }

        /**
         * Returns the key for this entry.
         * 
         * @return the entry key.
         */
        public final int getKey() {
            return _key;
        }

        /**
         * Returns the entry after this one.
         * 
         * @return the next entry.
         */
        public Entry getNextEntry() {
            return _next;
        }

        /**
         * Returns the entry before this one.
         * 
         * @return the previous entry.
         */
        public Entry getPreviousEntry() {
            return _previous;
        }

        /**
         * Returns the value for this entry.
         * 
         * @return the entry value.
         */
        public final Object getValue() {
            return _value;
        }

        /**
         * Returns the hash code for this entry.
         * 
         * @return this entry hash code.
         */
        public int hashCode() {
            return _key ^ ((_value != null) ? _value.hashCode() : 0);
        }

        /**
         * Sets the value for this entry.
         * 
         * @param value the new value.
         * @return the previous value.
         */
        public final Object setValue(Object value) {
            Object old = _value;
            _value = value;
            return old;
        }

        /**
         * Detaches this entry from the entry table and list.
         */
        private void detach() {
            // Removes from list.
            _previous._next = _next;
            _next._previous = _previous;

            // Removes from bucket.
            final int index = _keyHash & (_table.length - 1);
            final Entry beside = _beside;
            Entry previous = _table[index];
            if (previous == this) { // First in bucket.
                _table[index] = beside;
            } else {
                while (previous._beside != this) {
                    previous = previous._beside;
                }
                previous._beside = beside;
            }
        }
    }

    public class EntryIterator {

        private int _currentIndex;
        private Entry _currentNode;
        private int _nextIndex;
        private Entry _nextNode;

        public EntryIterator() {
            _nextNode = _head._next;
            _currentNode = null;
            _nextIndex = 0;
            _currentIndex = -1;
        }

        public void addEntry(int hash, int key, Object value) {
            IntHashMap.this.addEntry(hash, key, value);
            _currentNode = null;
            _nextIndex++;
            _currentIndex = -1;
        }

        public Entry currentEntry() {
            if (!hasCurrent())
                throw new NoSuchElementException();
            return _currentNode;
        }

        public int currentIndex() {
            return _currentIndex;
        }

        public Entry firstEntry()  {
            reset();
            return peekNextEntry();
        }

        public boolean hasCurrent() {
            return (_currentNode != null);
        }

        public boolean hasNext() {
            return (_nextIndex < IntHashMap.this._size);
        }

        public boolean hasPrevious() {
            return _nextIndex > 0;
        }

        public boolean isEmpty() {
            return IntHashMap.this.isEmpty();
        }

        public Entry lastEntry()  {
            if (!hasNext()) {
                previousEntry();
            }
            Entry entry = null;
            while (hasNext()) {
                entry = nextEntry();
            }
            return entry;
        }

        public Entry nextEntry() {
            if (_nextIndex == IntHashMap.this._size)
                throw new NoSuchElementException();
            _currentIndex = _nextIndex;
            _nextIndex++;
            _currentNode = _nextNode;
            _nextNode = _nextNode._next;
            return _currentNode;
        }

        public int nextIndex() {
            return _nextIndex;
        }

        public Entry peekNextEntry()  {
            nextEntry();
            return previousEntry();
        }

        public Entry peekPreviousEntry()  {
            previousEntry();
            return nextEntry();
        }

        public Entry previousEntry() {
            if (_nextIndex == 0)
                throw new NoSuchElementException();
            _nextIndex--;
            _currentIndex = _nextIndex;
            _currentNode = _nextNode = _nextNode._previous;
            return _currentNode;
        }

        public int previousIndex() {
            return _nextIndex - 1;
        }

        public void remove() {
            if (_currentNode != null) {
                if (_nextNode == _currentNode) { // previous() has been called.
                    _nextNode = _nextNode._next;
                } else {
                    _nextIndex--;
                }
                IntHashMap.this.removeEntry(_currentNode);
                _currentNode = null;
                _currentIndex = -1;
            } else {
                throw new IllegalStateException();
            }
        }

        public void reset() {
            _nextNode = _head._next;
            _currentNode = null;
            _nextIndex = 0;
            _currentIndex = -1;
        }

        public void setEntry(Entry o) {
            if (_currentNode != null) {
                _currentNode = o;
            } else {
                throw new IllegalStateException();
            }
        }

        public int size()  {
            return IntHashMap.this._size;
        }
    }

    private class IntKeyIterator extends EntryIterator implements IntListIterator {
        public int next() {
            return nextEntry().getKey();
        }

        public void add(int element) {
            throw new UnsupportedOperationException();
        }

        public int previous() {
            return previousEntry().getKey();
        }

        public void set(int element) {
            throw new UnsupportedOperationException();
        }
    }

    public class ValueIterator extends EntryIterator {

        public void add(Object row) throws UnsupportedOperationException {
            throw new UnsupportedOperationException();
        }

        public Object current() throws NoSuchElementException {
            return currentEntry().getValue();
        }

        public Object first() throws NoSuchElementException {
            return firstEntry().getValue();
        }

        public Object last() throws NoSuchElementException {
            return lastEntry().getValue();
        }

        public Object next() throws NoSuchElementException {
            return nextEntry().getValue();
        }

        public Object peekNext() throws NoSuchElementException {
            return peekNextEntry().getValue();
        }

        public Object peekPrevious() throws NoSuchElementException {
            return peekPreviousEntry().getValue();
        }

        public Object previous() throws NoSuchElementException {
            return previousEntry().getValue();
        }

        public void set(Object row) throws UnsupportedOperationException {
            if (!hasCurrent()) {
                throw new IllegalStateException();
            }
            currentEntry().setValue(row);
        }

        public int next(int count)  {
            for (int i = 0; i < count; i++) {
                next();
            }
            return currentEntry().getKey();
        }

        public int previous(int count)  {
            for (int i = 0; i < count; i++) {
                previous();
            }
            return currentEntry().getKey();
        }

    }
    
    private class Keys implements IntCollection {

        public boolean add(int id) {
            throw new UnsupportedOperationException();
        }

        public void clear() {
            IntHashMap.this.clear();
        }

        public boolean contains(int id) {
            return IntHashMap.this.containsKey(id);
        }

        public boolean isEmpty() {
            return IntHashMap.this.isEmpty();
        }

        public IntIterator iterator() {
            return IntHashMap.this.keyIterator();
        }

        public boolean remove(int id) {
            return IntHashMap.this.remove(id) != null;
        }

        public int size() {
            return IntHashMap.this.size();
        }

        public boolean addAll(IntCollection c) {
            throw new UnsupportedOperationException();
        }

        public boolean containsAll(IntCollection c) {
            throw new UnsupportedOperationException();
        }

        public boolean removeAll(IntCollection c) {
            throw new UnsupportedOperationException();
        }

        public boolean removeElement(int element) {
            return IntHashMap.this.remove(element) != null;
        }

        public boolean retainAll(IntCollection c) {
            throw new UnsupportedOperationException();
        }

        public int[] toArray() {
            throw new UnsupportedOperationException();
        }

        public int[] toArray(int[] a) {
            throw new UnsupportedOperationException();
        }
    }
    
    protected class Values {

        public boolean add(Object row) {
            throw new UnsupportedOperationException();
        }

        public void clear() {
            IntHashMap.this.clear();
        }

        public ValueIterator iterator() {
            return valueIterator();
        }

        public int size() {
            return _size;
        }

        public boolean contains(Object row) {
            return IntHashMap.this.containsValue(row);
        }

        public boolean isEmpty() {
            return IntHashMap.this.isEmpty();
        }

        public boolean remove(Object row) {
            for (Entry r = headEntry(), end = tailEntry(); (r = r._next) != end;) {
                if (row.equals(r._value)) {
                    IntHashMap.this.removeEntry(r);
                    return true;
                }
            }
            return false;
        }
    }

    /** Holds the map's hash table (volatile for unsynchronized access). */
    private volatile transient Entry[] _entries;

    /**
     * Holds the head entry to which the first entry attaches. The head entry never
     * changes (entries always added last).
     */
    private transient Entry _head = newEntry();

    /** Holds a reference to a map having the old entries when resizing. */
    private transient IntHashMap _oldEntries;

    /** Holds the current size. */
    private transient int _size;

    /**
     * Holds the tail entry to which the last entry attaches. The tail entry changes as
     * entries are added/removed.
     */
    private transient Entry _tail = newEntry();

    /** Holds the values view. */
    private transient Values _values = new Values();
    
    /** Holds the keys view. */
    private transient Keys _keys = new Keys();
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.