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();
        }