public Map.Entry<K, V> next() {
            return nextNode();
        }

    }


    private final class AllValueIterator extends AbstractAllIterator implements Iterator<V> {

        protected AllValueIterator( boolean forward, Comparable<? super V> comp ) {
            super( forward, comp );
        }

        public V next() {
            return nextNode().mValue;
        }

    }


    private final class GroupKeyIterator extends AbstractGroupIterator implements Iterator<K> {

        protected GroupKeyIterator( boolean forward, G group, Comparable<? super V> comp ) {
            super( forward, group, comp );
        }

        public K next() {
            return nextNode().mKey;
        }

    }


    private final class GroupEntryIterator extends AbstractGroupIterator implements Iterator<Map.Entry<K, V>> {

        protected GroupEntryIterator( boolean forward, G group, Comparable<? super V> comp ) {
            super( forward, group, comp );
        }

        public Map.Entry<K, V> next() {
            return nextNode();
        }

    }


    private final class GroupValueIterator extends AbstractGroupIterator implements Iterator<V> {

        protected GroupValueIterator( boolean forward, G group, Comparable<? super V> comp ) {
            super( forward, group, comp );
        }

        public V next() {
            return nextNode().mValue;
        }

    }


    private final class GroupTableIterator implements Iterator<G> {
        GroupNode<K, V> mPrev;
        GroupNode<K, V> mNext;
        int             mIterModCount;
        int             mIndex;

        GroupTableIterator() {
            mIterModCount = mModCount;

            if( mGroupCount > 0 ) {
                GroupNode<K, V>[] buckets = mGroupBuckets;

                while( mIndex < buckets.length ) {
                    mNext = buckets[mIndex++];

                    if( mNext != null ) { break; }
                }
            }
        }


        public final boolean hasNext() {
            return mNext != null;
        }

        public final G next() {
            if( mModCount != mIterModCount ) { throw new ConcurrentModificationException(); }

            if( mNext == null ) { throw new NoSuchElementException(); }

            mPrev = mNext;
            mNext = mNext.mNext;
            GroupNode<K, V>[] buckets = mGroupBuckets;

            while( mNext == null ) {
                if( mIndex >= buckets.length ) { return (G)mPrev.mGroup; }

                mNext = buckets[mIndex++];
            }

            return (G)mPrev.mGroup;
        }

        public final void remove() {
            if( mPrev == null ) { throw new IllegalStateException(); }

            if( mModCount != mIterModCount ) { throw new ConcurrentModificationException(); }

            clear( (G)mPrev.mGroup );

            mPrev = null;
            mIterModCount = mModCount;
        }
    }


    /************
     * Views
     ************/

    private final class AllKeySet extends AbstractSet<K> {

        private final boolean               mForward;
        private final Comparable<? super V> mComp;

        AllKeySet( boolean forward, Comparable<? super V> comp ) {
            mForward = forward;
            mComp = comp;
        }


        public int size() {
            if( mComp == null ) {
                return mAllCount;
            } else {
                Iterator<K> iter  = iterator();
                int         count = 0;

                while( iter.hasNext() ) {
                    iter.next();
                    count++;
                }

                return count;
            }
        }

        public boolean contains( Object key ) {
            Node<K, V> node = findKeyNode( (K)key );
            if( node == null || mComp != null && mComp.compareTo( node.mValue ) != 0 ) { return false; }

            return true;
        }

        public boolean remove( Object key ) {
            if( key == null ) { return false; }

            Node<K, V> node = findKeyNode( (K)key );
            if( node == null || mComp != null && mComp.compareTo( node.mValue ) != 0 ) { return false; }

            removeNodeCompletely( node, true );
            return true;
        }

        public void clear() {
            if( mComp == null ) {
                GroupMap.this.clear();
                return;
            }

            Iterator<K> iter = iterator();

            while( iter.hasNext() ) {
                iter.next();
                iter.remove();
            }
        }

        public Iterator<K> iterator() {
            return new AllKeyIterator( mForward, mComp );
        }

    }


    private final class GroupKeySet extends AbstractSet<K> {

        private final boolean               mForward;
        private final G                     mGroup;
        private final Comparable<? super V> mComp;

        GroupKeySet( boolean forward, G group, Comparable<? super V> comp ) {
            mForward = forward;
            mGroup = group;
            mComp = comp;
        }


        public int size() {
            if( mComp == null ) {
                return GroupMap.this.size( mGroup );
            } else {
                Iterator<K> iter  = iterator();
                int         count = 0;

                while( iter.hasNext() ) {
                    iter.next();
                    count++;
                }

                return count;
            }
        }

        public boolean contains( Object key ) {
            Node<K, V> node = findKeyNode( (K)key );
            if( node == null || mComp != null && mComp.compareTo( node.mValue ) != 0 ) { return false; }

            G ga = (G)node.mGroup.mGroup;
            G gb = mGroup;
            if( ga != gb && (ga == null || !ga.equals( gb )) ) { return false; }

            return true;
        }

        public boolean remove( Object key ) {
            if( key == null ) { return false; }

            Node<K, V> node = findKeyNode( (K)key );
            if( node == null || mComp != null && mComp.compareTo( node.mValue ) != 0 ) { return false; }

            G ga = (G)node.mGroup.mGroup;
            G gb = mGroup;
            if( ga != gb && (ga == null || !ga.equals( gb )) ) { return false; }

            removeNodeCompletely( node, true );
            return true;
        }

        public void clear() {
            if( mComp == null ) {
                GroupMap.this.clear( mGroup );
                return;
            }

            Iterator<K> iter = iterator();

            while( iter.hasNext() ) {
                iter.next();
                iter.remove();
            }
        }

        public Iterator<K> iterator() {
            return new GroupKeyIterator( mForward, mGroup, mComp );
        }

    }


    private final class AllEntrySet extends AbstractSet<Map.Entry<K, V>> {

        private final boolean               mForward;
        private final Comparable<? super V> mComp;

        AllEntrySet( boolean forward, Comparable<? super V> comp ) {
            mForward = forward;
            mComp = comp;
        }


        public int size() {
            if( mComp == null ) {
                return mAllCount;
            } else {
                Iterator<Map.Entry<K, V>> iter  = iterator();
                int                       count = 0;

                while( iter.hasNext() ) {
                    iter.next();
                    count++;
                }

                return count;
            }
        }

        public boolean contains( Object entry ) {
            if( entry == null ) { return false; }

            Map.Entry<K, V> e = (Map.Entry<K, V>)entry;

            Node<K, V> node = findKeyNode( e.getKey() );
            if( node == null || mComp != null && mComp.compareTo( node.mValue ) != 0 ) { return false; }

            V va = e.getValue();
            V vb = node.mValue;
            if( va != vb && (va == null || !va.equals( vb )) ) { return false; }

            return true;
        }

        public boolean remove( Object entry ) {
            if( entry == null ) { return false; }

            Map.Entry<K, V> e = (Map.Entry<K, V>)entry;

            Node<K, V> node = findKeyNode( e.getKey() );
            if( node == null || mComp != null && mComp.compareTo( node.mValue ) != 0 ) { return false; }

            V va = e.getValue();
            V vb = node.mValue;
            if( va != vb && (va == null || !va.equals( vb )) ) { return false; }

            removeNodeCompletely( node, true );
            return true;
        }

        public void clear() {
            if( mComp == null ) {
                GroupMap.this.clear();
                return;
            }

            Iterator<Map.Entry<K, V>> iter = iterator();

            while( iter.hasNext() ) {
                iter.next();
                iter.remove();
            }
        }

        public Iterator<Map.Entry<K, V>> iterator() {
            return new AllEntryIterator( mForward, mComp );
        }

    }


    private final class GroupEntrySet extends AbstractSet<Map.Entry<K, V>> {

        private final boolean               mForward;
        private final G                     mGroup;
        private final Comparable<? super V> mComp;

        GroupEntrySet( boolean forward, G group, Comparable<? super V> comp ) {
            mForward = forward;
            mGroup = group;
            mComp = comp;
        }


        public int size() {
            if( mComp == null ) {
                return GroupMap.this.size( mGroup );
            } else {
                Iterator<Map.Entry<K, V>> iter  = iterator();
                int                       count = 0;

                while( iter.hasNext() ) {
                    iter.next();
                    count++;
                }

                return count;
            }
        }

        public boolean contains( Object entry ) {
            if( entry == null ) { return false; }

            Map.Entry<K, V> e = (Map.Entry<K, V>)entry;

            Node<K, V> node = findKeyNode( e.getKey() );
            if( node == null || mComp != null && mComp.compareTo( node.mValue ) != 0 ) { return false; }

            G ga = (G)node.mGroup.mGroup;
            G gb = mGroup;
            if( ga != gb && (ga == null || !ga.equals( gb )) ) { return false; }

            V va = node.mValue;
            V vb = e.getValue();
            if( va != vb && (va == null || !va.equals( vb )) ) { return false; }

            return true;
        }

        public boolean remove( Object entry ) {
            if( entry == null ) { return false; }

            Map.Entry<K, V> e = (Map.Entry<K, V>)entry;

            Node<K, V> node = findKeyNode( e.getKey() );
            if( node == null || mComp != null && mComp.compareTo( node.mValue ) != 0 ) { return false; }

            G ga = (G)node.mGroup.mGroup;
            G gb = mGroup;
            if( ga != gb && (ga == null || !ga.equals( gb )) ) { return false; }

            V va = node.mValue;
            V vb = e.getValue();
            if( va != vb && (va == null || !va.equals( vb )) ) { return false; }

            removeNodeCompletely( node, true );
            return true;
        }

        public void clear() {
            if( mComp == null ) {
                GroupMap.this.clear( mGroup );
                return;
            }

            Iterator<Map.Entry<K, V>> iter = iterator();

            while( iter.hasNext() ) {
                iter.next();
                iter.remove();
            }
        }

        public Iterator<Map.Entry<K, V>> iterator() {
            return new GroupEntryIterator( mForward, mGroup, mComp );
        }

    }


    private final class AllValues extends AbstractCollection<V> {

        private final boolean               mForward;
        private final Comparable<? super V> mComp;

        AllValues( boolean forward, Comparable<? super V> comp ) {
            mForward = forward;
            mComp = comp;
        }


        public int size() {
            if( mComp == null ) {
                return mAllCount;
            } else {
                Iterator<V> iter  = iterator();
                int         count = 0;

                while( iter.hasNext() ) {
                    iter.next();
                    count++;
                }

                return count;
            }
        }

        public boolean contains( Object value ) {
            if( mComp != null && mComp.compareTo( (V)value ) != 0 ) { return false; }

            return findNodeThatContains( value ) != null;
        }

        public boolean remove( Object value ) {
            if( mComp != null && mComp.compareTo( (V)value ) != 0 ) { return false; }

            Node<K, V> node = findNodeThatContains( value );
            if( node == null ) { return false; }

            removeNodeCompletely( node, true );
            return true;
        }

        public void clear() {
            if( mComp == null ) {
                GroupMap.this.clear();
                return;
            }

            Iterator<V> iter = iterator();

            while( iter.hasNext() ) {
                iter.next();
                iter.remove();
            }
        }

        public Iterator<V> iterator() {
            return new AllValueIterator( mForward, mComp );
        }

    }


    private final class GroupValues extends AbstractCollection<V> {

        private final boolean               mForward;
        private final G                     mGroup;
        private final Comparable<? super V> mComp;

        GroupValues( boolean forward, G group, Comparable<? super V> comp ) {
            mForward = forward;
            mGroup = group;
            mComp = comp;
        }


        public int size() {
            if( mComp == null ) {
                return GroupMap.this.size( mGroup );
            } else {
                Iterator<V> iter  = iterator();
                int         count = 0;

                while( iter.hasNext() ) {
                    iter.next();
                    count++;
                }

                return count;
            }
        }

        public boolean contains( Object value ) {
            if( mComp != null && mComp.compareTo( (V)value ) != 0 ) { return false; }

            return findNodeThatContains( mGroup, value ) != null;
        }

        public boolean remove( Object value ) {
            if( mComp != null && mComp.compareTo( (V)value ) != 0 ) { return false; }

            Node<K, V> node = findNodeThatContains( mGroup, value );
            if( node == null ) { return false; }

            removeNodeCompletely( node, true );
            return true;
        }

        public void clear() {
            if( mComp == null ) {
                GroupMap.this.clear( mGroup );
                return;
            }

            Iterator<V> iter = iterator();

            while( iter.hasNext() ) {
                iter.next();
                iter.remove();
            }
        }

        public Iterator<V> iterator() {
            return new GroupValueIterator( mForward, mGroup, mComp );
        }

    }


    private final class Groups extends AbstractSet<G> {

        public int size() {
            return mGroupCount;
        }

        public boolean contains( Object group ) {
            return findGroupNode( group ) != null;
        }

        public boolean remove( Object group ) {
            GroupNode<K, V> node = findGroupNode( group );
            if( node == null ) { return false; }

            GroupMap.this.clear( (G)node.mGroup );
            return true;
        }

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

        public Iterator<G> iterator() {
            return new GroupTableIterator();
        }