home *** CD-ROM | disk | FTP | other *** search
/ Symantec Visual Cafe for Java 2.5 / symantec-visual-cafe-2.5-database-dev-edition.iso / Extras / OSpace / jgl.exe / jgl_2_0 / src / COM / objectspace / jgl / Deque.java < prev    next >
Encoding:
Java Source  |  1997-03-14  |  30.3 KB  |  1,006 lines

  1. // Copyright(c) 1996,1997 ObjectSpace, Inc.
  2. // Portions Copyright(c) 1995, 1996 Hewlett-Packard Company.
  3.  
  4. package COM.objectspace.jgl;
  5.  
  6. import java.util.Enumeration;
  7.  
  8. /**
  9.  * A Deque is a sequential container that is optimized for fast indexed-based access
  10.  * and efficient insertion at either of its extremities.
  11.  * <p>
  12.  * Deques are useful in circumstances where order, compact storage, and fast insertion at
  13.  * extremeties is important. A Deque is ideal for implementing any kind of FIFO structure.
  14.  * If a strict FIFO structure is required that does not allow index-based access, then
  15.  * you should consider using a Queue adaptor with a Deque as the underlying container.
  16.  * If you require very fast insertion near the middle of a sequential structure, then
  17.  * consider using a List instead of a Deque.
  18.  * <p>
  19.  * The implementation allocates storage for a Deque's elements in 4K blocks
  20.  * (a usual page size) of contiguous memory, and use an array to keep track of a deque's
  21.  * blocks. When a Deque is constructed, it has no associated storage. As elements are
  22.  * added, blocks of storage are added to the beginning or the end of the deque as
  23.  * necessary. A result of this architecture is that items may be inserted very
  24.  * efficiently near either extremity. Once a block has been allocated to a Deque, it is
  25.  * not deallocated until the Deque is destroyed. Insertions are careful to expand the
  26.  * Deque in the direction that involves the least amount of copying. Removals take
  27.  * similar precautions.
  28.  * <p>
  29.  * If an insertion causes reallocation, all iterators and references are invalidated;
  30.  * otherwise, iterators and references are only invalidated if an item is not inserted
  31.  * at an extremity. In the worst cast, inserting a single element into a Deque takes
  32.  * linear time in the minimum of the distance from the insertion point to the beginning
  33.  * of the Deque and the distance from the insertion point to the end of the Deque.
  34.  * Inserting a single element either at the beginning or end of a Deque always takes
  35.  * constant time.
  36.  * <p>
  37.  * If the first or last item is removed, all iterators and references remain valid; if any
  38.  * other item is removed, all iterators and references are invalidated.
  39.  * <p>
  40.  * @see COM.objectspace.jgl.Sequence
  41.  * @see COM.objectspace.jgl.examples.DequeExamples
  42.  * @version 2.0.2
  43.  * @author ObjectSpace, Inc.
  44.  */
  45.  
  46. public class Deque implements Sequence
  47.   {
  48.   DequeIterator myStart = new DequeIterator( this, 0, 0 );
  49.   DequeIterator myFinish = new DequeIterator( this, 0, 0 );
  50.   int myLength;
  51.   Object[][] myMap;
  52.   static final int BLOCK_SIZE = Allocator.pageSize() / 8;
  53.  
  54.   /**
  55.    * Construct myself to be an empty Deque.
  56.    */
  57.   public Deque()
  58.     {
  59.     }
  60.  
  61.   /**
  62.    * Construct myself to contain a specified number of null elements.
  63.    * @param size The number of elements to contain.
  64.    * @exception java.lang.IllegalArgumentException If size is negative.
  65.    */
  66.   public Deque( int size )
  67.     {
  68.     insert( myStart, size, null );
  69.     }
  70.  
  71.   /**
  72.    * Construct myself to contain a specified number of elements set to
  73.    * a particular object.
  74.    * @param size The number of elements to contain.
  75.    * @param object The initial value of each element.
  76.    * @exception java.lang.IllegalArgumentException If size is negative.
  77.    */
  78.   public Deque( int size, Object object )
  79.     {
  80.     insert( myStart, size, object );
  81.     }
  82.  
  83.   /**
  84.    * Construct myself to be a shallow copy of an existing Deque.
  85.    * @param deque The Deque to copy.
  86.    */
  87.   public Deque( Deque deque )
  88.     {
  89.     synchronized( deque )
  90.       {
  91.       Copying.copy( deque, new InsertIterator( this ) );
  92.       }
  93.     }
  94.  
  95.   /**
  96.    * Return a shallow copy of myself.
  97.    */
  98.   public synchronized Object clone()
  99.     {
  100.     return new Deque( this );
  101.     }
  102.  
  103.   /**
  104.    * Return true if I'm equal to another object.
  105.    * @param object The object to compare myself against.
  106.    */
  107.   public boolean equals( Object object )
  108.     {
  109.     return object instanceof Deque && equals( (Deque)object );
  110.     }
  111.  
  112.   /**
  113.    * Return true if I contain the same items in the same order as
  114.    * another Deque. Use equals() to compare the individual elements.
  115.    * @param deque The Deque to compare myself against.
  116.    */
  117.   public synchronized boolean equals( Deque deque )
  118.     {
  119.     synchronized( deque )
  120.       {
  121.       return Comparing.equal( this, deque );
  122.       }
  123.     }
  124.  
  125.   /**
  126.    * Return my hash code for support of hashing containers
  127.    */
  128.   public synchronized int hashCode()
  129.     {
  130.     return Hashing.orderedHash( this );
  131.     }
  132.  
  133.  
  134.   /**
  135.    * Return a string that describes me.
  136.    */
  137.   public synchronized String toString()
  138.     {
  139.     return Printing.toString( this, "Deque" );
  140.     }
  141.  
  142.   /**
  143.    * Become a shallow copy of an existing Deque.
  144.    * @param deque The Deque that I shall become a shallow copy of.
  145.    */
  146.   public synchronized void copy( Deque deque )
  147.     {
  148.     if ( this == deque )
  149.       return;
  150.  
  151.     synchronized( deque )
  152.       {
  153.       if ( myLength >= deque.myLength )
  154.         {
  155.         DequeIterator begin = (DequeIterator) Copying.copy( deque.myStart, deque.myFinish, myStart );
  156.         remove( begin, myFinish );
  157.         }
  158.       else
  159.         {
  160.         DequeIterator end = deque.myStart.copy( myLength );
  161.         Copying.copy( deque.myStart, end, myStart );
  162.  
  163.         for ( DequeIterator iterator = end; iterator.hasMoreElements(); iterator.advance() )
  164.           add( iterator.get() );
  165.         }
  166.       }
  167.     }
  168.  
  169.   /**
  170.    * Return true if I contain no entries.
  171.    */
  172.   public boolean isEmpty()
  173.     {
  174.     return myLength == 0;
  175.     }
  176.  
  177.   /**
  178.    * Return the number of entries that I contain.
  179.    */
  180.   public int size()
  181.     {
  182.     return myLength;
  183.     }
  184.  
  185.   /**
  186.    * Return the maximum number of entries that I can contain.
  187.    */
  188.   public int maxSize()
  189.     {
  190.     return Allocator.maxSize();
  191.     }
  192.  
  193.   /**
  194.    * Add an object after my last element and return null.
  195.    * This function is a synonym for pushBack().
  196.    * @param object The object to add.
  197.    */
  198.   public synchronized Object add( Object object )
  199.     {
  200.     if ( myLength++ == 0 )
  201.       {
  202.       createMap();
  203.       myMap[ myFinish.myMapIndex ][ myFinish.myBlockIndex++ ] = object;
  204.       }
  205.     else
  206.       {
  207.       myMap[ myFinish.myMapIndex ][ myFinish.myBlockIndex++ ] = object;
  208.  
  209.       if ( myFinish.myBlockIndex == BLOCK_SIZE )
  210.         {
  211.         if ( myFinish.myMapIndex == myMap.length - 1 )
  212.           growMap();
  213.  
  214.         myMap[ ++myFinish.myMapIndex ] = new Object[ BLOCK_SIZE ];
  215.         myFinish.myBlockIndex = 0;
  216.         }
  217.       }
  218.       return null;
  219.     }
  220.  
  221.   /**
  222.    * Add an object after my last element.
  223.    * @param The object to add.
  224.    */
  225.   public void pushBack( Object object )
  226.     {
  227.     add( object );
  228.     }
  229.  
  230.   /**
  231.    * Insert an object in front of my first element.
  232.    * @param object The object to insert.
  233.    */
  234.   public synchronized void pushFront( Object object )
  235.     {
  236.     if ( myLength == 0 )
  237.       {
  238.       add( object );
  239.       return;
  240.       }
  241.  
  242.     ++myLength;
  243.     if ( --myStart.myBlockIndex < 0 )
  244.       {
  245.       if ( myStart.myMapIndex == 0 )
  246.         growMap();
  247.  
  248.       myMap[ --myStart.myMapIndex ] = new Object[ BLOCK_SIZE ];
  249.       myStart.myBlockIndex = BLOCK_SIZE - 1;
  250.       }
  251.  
  252.     myMap[ myStart.myMapIndex ][ myStart.myBlockIndex ] = object;
  253.     }
  254.  
  255.   /**
  256.    * Remove and return my first element.
  257.    * @exception COM.objectspace.jgl.InvalidOperationException If the Deque is empty.
  258.    */
  259.   public synchronized Object popFront()
  260.     {
  261.     if ( myLength == 0 )
  262.       throw new InvalidOperationException( "Deque is empty" );
  263.  
  264.     Object r = at(0);
  265.     if ( --myLength == 0 )
  266.       {
  267.       clear();
  268.       }
  269.     else
  270.       {
  271.       r = myMap[ myStart.myMapIndex ][ myStart.myBlockIndex ];
  272.       myMap[ myStart.myMapIndex ][ myStart.myBlockIndex++ ] = null;
  273.  
  274.       if ( myStart.myBlockIndex == BLOCK_SIZE )
  275.         {
  276.         myMap[ myStart.myMapIndex++ ] = null;
  277.         myStart.myBlockIndex = 0;
  278.         }
  279.       }
  280.     return r;
  281.     }
  282.  
  283.   /**
  284.    * Remove and return my last element.
  285.    * @exception COM.objectspace.jgl.InvalidOperationException If the Deque is empty.
  286.    */
  287.   public synchronized Object popBack()
  288.     {
  289.     if ( myLength == 0 )
  290.       throw new InvalidOperationException( "Deque is empty" );
  291.  
  292.     Object r = at(0);
  293.     if ( --myLength == 0 )
  294.       {
  295.       clear();
  296.       }
  297.     else
  298.       {
  299.       if ( myFinish.myBlockIndex-- == 0 )
  300.         {
  301.         myMap[ myFinish.myMapIndex-- ] = null;
  302.         myFinish.myBlockIndex = BLOCK_SIZE - 1;
  303.         }
  304.       r = myMap[ myFinish.myMapIndex ][ myFinish.myBlockIndex ];
  305.       myMap[ myFinish.myMapIndex ][ myFinish.myBlockIndex ] = null;
  306.       }
  307.     return r;
  308.     }
  309.  
  310.   /**
  311.    * Remove all of my elements.
  312.    */
  313.   public synchronized void clear()
  314.     {
  315.     myMap = null;
  316.     myStart.myMapIndex = 0;
  317.     myStart.myBlockIndex = 0;
  318.     myFinish.myMapIndex = 0;
  319.     myFinish.myBlockIndex = 0;
  320.     myLength = 0;
  321.     }
  322.  
  323.   /**
  324.    * Return an Enumeration of my components
  325.    */
  326.   public synchronized Enumeration elements()
  327.     {
  328.     return new DequeIterator( myStart );
  329.     }
  330.  
  331.   /**
  332.    * Return an iterator positioned at my first item.
  333.    */
  334.   public synchronized DequeIterator begin()
  335.     {
  336.     return new DequeIterator( myStart );
  337.     }
  338.  
  339.   /**
  340.    * Return an iterator positioned immediately after my last item.
  341.    */
  342.   public synchronized DequeIterator end()
  343.     {
  344.     return new DequeIterator( myFinish );
  345.     }
  346.  
  347.   /**
  348.    * Return an iterator positioned at my first item
  349.    */
  350.   public ForwardIterator start()
  351.     {
  352.     return begin();
  353.     }
  354.  
  355.   /**
  356.    * Return an iterator positioned immediately afer my last item.
  357.    */
  358.   public ForwardIterator finish()
  359.     {
  360.     return end();
  361.     }
  362.  
  363.   /**
  364.    * Return my first item.
  365.    * @exception COM.objectspace.jgl.InvalidOperationException If the Deque is empty.
  366.    */
  367.   public synchronized Object front()
  368.     {
  369.     if ( myLength == 0 )
  370.       throw new InvalidOperationException( "Deque is empty" );
  371.  
  372.     return myMap[ myStart.myMapIndex ][ myStart.myBlockIndex ];
  373.     }
  374.  
  375.   /**
  376.    * Return my last item.
  377.    * @exception COM.objectspace.jgl.InvalidOperationException If the Deque is empty.
  378.    */
  379.   public synchronized Object back()
  380.     {
  381.     if ( myLength == 0 )
  382.       throw new InvalidOperationException( "Deque is empty" );
  383.  
  384.     if ( myFinish.myBlockIndex > 0 )
  385.       return myMap[ myFinish.myMapIndex ][ myFinish.myBlockIndex - 1 ];
  386.     else
  387.       return myMap[ myFinish.myMapIndex - 1 ][ BLOCK_SIZE - 1 ];
  388.     }
  389.  
  390.   /**
  391.    * Return the element at the specified index.
  392.    * @param index The index.
  393.    * @exception java.lang.IndexOutOfBoundsException If the index is invalid.
  394.    */
  395.   public synchronized Object at( int index )
  396.     {
  397.     if ( index < 0 || index >= myLength )
  398.       throw new IndexOutOfBoundsException( "Attempt to access index " + index + " when valid range is 0.." + (myLength - 1) );
  399.  
  400.     int blockIndex = myStart.myBlockIndex + index;
  401.     int mapIndex = myStart.myMapIndex;
  402.  
  403.     if ( blockIndex >= BLOCK_SIZE )
  404.       {
  405.       int jump = blockIndex / BLOCK_SIZE;
  406.       mapIndex += jump;
  407.       blockIndex %= BLOCK_SIZE;
  408.       }
  409.     else if ( blockIndex < 0 )
  410.       {
  411.       int jump = ( BLOCK_SIZE - 1 - blockIndex ) / BLOCK_SIZE;
  412.       mapIndex -= jump;
  413.       blockIndex += jump * BLOCK_SIZE;
  414.       }
  415.  
  416.     return myMap[ mapIndex ][ blockIndex ];
  417.     }
  418.  
  419.   /**
  420.    * Set the element at the specified index to a particular object.
  421.    * @param index The index.
  422.    * @param object The object.
  423.    * @exception java.lang.IndexOutOfBoundsException If the index is invalid.
  424.    */
  425.   public synchronized void put( int index, Object object )
  426.     {
  427.     if ( index < 0 || index >= myLength )
  428.       throw new IndexOutOfBoundsException( "Attempt to access index " + index + " when valid range is 0.." + (myLength - 1) );
  429.  
  430.     int blockIndex = myStart.myBlockIndex + index;
  431.     int mapIndex = myStart.myMapIndex;
  432.  
  433.     if ( blockIndex >= BLOCK_SIZE )
  434.       {
  435.       int jump = blockIndex / BLOCK_SIZE;
  436.       mapIndex += jump;
  437.       blockIndex %= BLOCK_SIZE;
  438.       }
  439.     else if ( blockIndex < 0 )
  440.       {
  441.       int jump = ( BLOCK_SIZE - 1 - blockIndex ) / BLOCK_SIZE;
  442.       mapIndex -= jump;
  443.       blockIndex += jump * BLOCK_SIZE;
  444.       }
  445.  
  446.     myMap[ mapIndex ][ blockIndex ] = object;
  447.     }
  448.  
  449.   /**
  450.    * Swap my contents with another Deque.
  451.    * @param deque The Deque that I will swap my contents with.
  452.    */
  453.   public synchronized void swap( Deque deque )
  454.     {
  455.     synchronized( deque )
  456.       {
  457.       DequeIterator tmpStart = myStart;
  458.       myStart = deque.myStart;
  459.       myStart.myDeque = this;
  460.       deque.myStart = tmpStart;
  461.       deque.myStart.myDeque = deque;
  462.  
  463.       DequeIterator tmpFinish = myFinish;
  464.       myFinish = deque.myFinish;
  465.       myFinish.myDeque = this;
  466.       deque.myFinish = tmpFinish;
  467.       deque.myFinish.myDeque = deque;
  468.  
  469.       int tmpLength = myLength;
  470.       myLength = deque.myLength;
  471.       deque.myLength = tmpLength;
  472.  
  473.       Object[][] tmpMap = myMap;
  474.       myMap = deque.myMap;
  475.       deque.myMap = tmpMap;
  476.       }
  477.     }
  478.  
  479.   /**
  480.    * Remove the element at a particular index.
  481.    * @param index The index of the element to remove.
  482.    * @return The object removed.
  483.    * @exception java.lang.IndexOutOfBoundsException If the index is invalid.
  484.    */
  485.   public synchronized Object remove( int index )
  486.     {
  487.     if ( index < 0 || index >= myLength )
  488.       throw new IndexOutOfBoundsException( "Attempt to access index " + index + " when valid range is 0.." + (myLength - 1) );
  489.  
  490.     return remove( myStart.copy( index ) );
  491.     }
  492.  
  493.   /**
  494.    * Remove the element at a particular position.
  495.    * @param e An Enumeration positioned at the element to remove.
  496.    * @return The object removed.
  497.    * @exception IllegalArgumentException if the Enumeration isn't a
  498.    * DequeIterator for this Deque object.
  499.    */
  500.   public synchronized Object remove( Enumeration e )
  501.     {
  502.     if ( ! (e instanceof DequeIterator) )
  503.       throw new IllegalArgumentException( "Enumeration not a DequeIterator" );
  504.  
  505.     if ( ((DequeIterator)e).myDeque != this )
  506.       throw new IllegalArgumentException( "Enumeration not for this Deque" );
  507.  
  508.     DequeIterator pos = (DequeIterator)e;
  509.     Object retval = pos.get();
  510.     DequeIterator tmp = pos.copy( 1 );
  511.  
  512.     if ( myStart.distance( pos ) < pos.distance( myFinish ) )
  513.       {
  514.       Copying.copy( tmp, myFinish, pos );
  515.       popBack();
  516.       }
  517.     else
  518.       {
  519.       Copying.copyBackward( myStart, pos, tmp );
  520.       popFront();
  521.       }
  522.  
  523.     return retval;
  524.     }
  525.  
  526.   /**
  527.    * Remove the elements within a range of indices.
  528.    * @param first The index of the first element to remove.
  529.    * @param last The index of the last element to remove.
  530.    * @return The number of elements removed.
  531.    * @exception java.lang.IndexOutOfBoundsException If either index is invalid.
  532.    */
  533.   public synchronized int remove( int first, int last )
  534.     {
  535.     if ( last < first )
  536.       return 0;
  537.  
  538.     checkRange( first, last );
  539.     return remove( myStart.copy( first ), myStart.copy( last + 1 ) );
  540.     }
  541.  
  542.   /**
  543.    * Remove the elements in the range [ first..last ).
  544.    * @param first An Enumeration positioned at the first element to remove.
  545.    * @param last An Enumeration positioned immediately after the last element to remove.
  546.    * @return The number of elements removed.
  547.    * @exception IllegalArgumentException if the Enumeration isn't a
  548.    * DequeIterator for this Deque object.
  549.    */
  550.   public synchronized int remove( Enumeration first, Enumeration last )
  551.     {
  552.     if ( ( ! (first instanceof DequeIterator) ) ||
  553.         ( ! (last instanceof DequeIterator) ) )
  554.       throw new IllegalArgumentException( "Enumeration not a DequeIterator" );
  555.  
  556.     if ( ( ((DequeIterator)first).myDeque != this ) ||
  557.         ( ((DequeIterator)last).myDeque != this ) )
  558.       throw new IllegalArgumentException( "Enumeration not for this Deque" );
  559.  
  560.     DequeIterator begin = (DequeIterator)first;
  561.     DequeIterator end = (DequeIterator)last;
  562.  
  563.     int n = begin.distance( end );
  564.     int count = n;
  565.  
  566.     if ( end.distance( myFinish ) > myStart.distance( begin ) )
  567.       {
  568.       Copying.copyBackward( myStart, begin, end );
  569.  
  570.       while ( n-- > 0 )
  571.         popFront();
  572.       }
  573.     else
  574.       {
  575.       Copying.copy( end, myFinish, begin );
  576.  
  577.       while ( n-- > 0 )
  578.         popBack();
  579.       }
  580.  
  581.     return count;
  582.     }
  583.  
  584.   /**
  585.    * Insert an object at a particular index and return an iterator
  586.    * positioned at the new element.
  587.    * @param index The index of the element that the object will be inserted immediately before.
  588.    * @param object The object to insert.
  589.    * @exception java.lang.IndexOutOfBoundsException If the index is invalid.
  590.    */
  591.   public synchronized DequeIterator insert( int index, Object object )
  592.     {
  593.     if ( index < 0 || index > myLength )
  594.       throw new IndexOutOfBoundsException( "Attempt to insert at index " + index + " when valid range is 0.." + myLength );
  595.  
  596.     return insert( myStart.copy( index ), object );
  597.     }
  598.  
  599.   /**
  600.    * Insert an object at a particular position and return an iterator
  601.    * positioned at the new element.
  602.    * @param pos An iterator positioned at the element that the object will be inserted immediately before.
  603.    * @param object The object to insert.
  604.    */
  605.   public synchronized DequeIterator insert( DequeIterator pos, Object value )
  606.     {
  607.     if ( pos.equals( myStart ) )
  608.       {
  609.       pushFront( value );
  610.       return new DequeIterator( myStart );
  611.       }
  612.     else if ( pos.equals( myFinish ) )
  613.       {
  614.       pushBack( value );
  615.       return myFinish.copy( -1 );
  616.       }
  617.     else
  618.       {
  619.       int index = myStart.distance( pos );
  620.  
  621.       if ( pos.distance( myFinish ) > index )
  622.         {
  623.         pushFront( myStart.get() );
  624.         Copying.copy( myStart.copy( 2 ), myStart.copy( index + 1 ), myStart.copy( 1 ) );
  625.         DequeIterator i = myStart.copy( index );
  626.         i.put( value );
  627.         return i;
  628.         }
  629.       else
  630.         {
  631.         DequeIterator i2 = myFinish.copy( -1 );
  632.         pushBack( i2.get() );
  633.         DequeIterator i = myStart.copy( index );
  634.         Copying.copyBackward( i, myFinish.copy( -2 ), myFinish.copy( -1 ) );
  635.         i.put( value );
  636.         return i;
  637.         }
  638.       }
  639.     }
  640.  
  641.   /**
  642.    * Insert multiple objects at a particular index.
  643.    * @param index The index of the element that the objects will be inserted immediately before.
  644.    * @param object The object to insert.
  645.    * @exception java.lang.IndexOutOfBoundsException If the index is invalid.
  646.    * @exception java.lang.IllegalArgumentException If the number of objects to insert is negative.
  647.    */
  648.   public synchronized void insert( int index, int n, Object value )
  649.     {
  650.     if ( n < 0 )
  651.       throw new IllegalArgumentException( "Attempt to insert a negative n1umber of objects." );
  652.  
  653.     if ( index < 0 || index > myLength )
  654.       throw new IndexOutOfBoundsException( "Attempt to insert at index " + index + " when valid range is 0.." + myLength );
  655.  
  656.     insert( myStart.copy( index ), n , value );
  657.     }
  658.  
  659.   /**
  660.    * Insert multiple objects at a particular position.
  661.    * @param pos An iterator positioned at the element that the objects will be inserted immediately before.
  662.    * @param n The number of objects to insert.
  663.    * @param object The object to insert.
  664.    * @exception java.lang.IllegalArgumentException If the number of objects to insert is negative.
  665.    */
  666.   public synchronized void insert( DequeIterator pos, int n, Object value )
  667.     {
  668.     if ( n < 0 )
  669.       throw new IllegalArgumentException( "Attempt to insert a negative number of objects" );
  670.  
  671.     if ( n == 0 )
  672.       return;
  673.  
  674.     int left = myStart.distance( pos ); // Number to left of insertion point.
  675.     int right = pos.distance( myFinish ); // Number to right of insertion point.
  676.  
  677.     if ( right > left )
  678.       {
  679.       if ( n > left )
  680.         {
  681.         int m = n - left;
  682.  
  683.         while ( m-- > 0 )
  684.           pushFront( value );
  685.  
  686.         for ( int j = 1; j <= left; j++ )
  687.           pushFront( at( n - 1 ) );
  688.  
  689.         Filling.fill( myStart.copy( n ), myStart.copy( n + left ), value );
  690.         }
  691.       else
  692.         {
  693.         for ( int j = 1; j <= n; j++ )
  694.           pushFront( at( n - 1 ) );
  695.  
  696.         DequeIterator i = myStart.copy( n + left );
  697.         Copying.copy( myStart.copy( n + n ), i, myStart.copy( n ) );
  698.         Filling.fill( myStart.copy( left ), i, value );
  699.         }
  700.       }
  701.     else
  702.       {
  703.       int oldSize = size(); // Size of deque before insertion.
  704.  
  705.       if ( n > right )
  706.         {
  707.         int m = n - right;
  708.  
  709.         while ( m-- > 0 )
  710.           pushBack( value );
  711.  
  712.         for ( int j = left; j < oldSize; j++ )
  713.           pushBack( at( j ) );
  714.  
  715.         Filling.fill( myStart.copy( left ), myStart.copy( oldSize ), value );
  716.         }
  717.       else
  718.         {
  719.         int index = oldSize - n;
  720.  
  721.         for ( int j = index; j < oldSize; j++ )
  722.           pushBack( at( j ) );
  723.  
  724.         DequeIterator i = myStart.copy( left );
  725.         Copying.copyBackward( i, myStart.copy( index ), myStart.copy( oldSize) );
  726.         Filling.fill( i, myStart.copy( left + n ), value );
  727.         }
  728.       }
  729.     }
  730.  
  731.   /**
  732.    * Insert a sequence of objects at a particular index.
  733.    * @param pos The index of the element that the objects will be inserted immediately before.
  734.    * @param first An iterator positioned at the first element to insert.
  735.    * @param last An iterator positioned immediately after the last element to insert.
  736.    * @exception java.lang.IndexOutOfBoundsException If the index is invalid.
  737.    */
  738.   public synchronized void insert( int index, BidirectionalIterator first, BidirectionalIterator last )
  739.     {
  740.     if ( index < 0 || index > myLength )
  741.       throw new IndexOutOfBoundsException( "Attempt to insert at index " + index + " when valid range is 0.." + myLength );
  742.  
  743.     insert( myStart.copy( index ), first, last );
  744.     }
  745.  
  746.   /**
  747.    * Insert a sequence of objects at a particular location.
  748.    * @param pos The location of the element that the objects will be inserted immediately before.
  749.    * @param first An iterator positioned at the first element to insert.
  750.    * @param last An iterator positioned immediately after the last element to insert.
  751.    */
  752.   public synchronized void insert( DequeIterator pos, BidirectionalIterator first, BidirectionalIterator last )
  753.     {
  754.     int n = first.distance( last );
  755.     int left = myStart.distance( pos ); // Number to left of insertion point.
  756.     int right = pos.distance( myFinish ); // Number to right of insertion point.
  757.  
  758.     if ( right > left )
  759.       {
  760.       if ( n > left )
  761.         {
  762.         BidirectionalIterator m = (BidirectionalIterator) last.clone();
  763.         m.retreat( left );
  764.         BidirectionalIterator q = (BidirectionalIterator) m.clone();
  765.  
  766.         while ( !m.equals( first ) )
  767.           {
  768.           m.retreat();
  769.           pushFront( m.get() );
  770.           }
  771.  
  772.         for ( int j = 1; j <= left; j++ )
  773.           pushFront( at( n - 1 ) );
  774.  
  775.         Copying.copy( q, last, myStart.copy( n ) );
  776.         }
  777.       else
  778.         {
  779.         for ( int j = 1; j <= n; j++ )
  780.           pushFront( at( n - 1 ) );
  781.  
  782.         Copying.copy( myStart.copy( n + n ), myStart.copy( n + left ), myStart.copy( n ) );
  783.         Copying.copy( first, last, myStart.copy( left ) );
  784.         }
  785.       }
  786.     else
  787.       {
  788.       int oldSize = size(); // Size of deque before insertion.
  789.  
  790.       if ( n > right )
  791.         {
  792.         BidirectionalIterator m = (BidirectionalIterator) first.clone();
  793.         m.advance( right );
  794.         BidirectionalIterator q = (BidirectionalIterator) m.clone();
  795.  
  796.         while ( !m.equals( last ) )
  797.           pushBack( m.nextElement() );
  798.  
  799.         for ( int j = left; j < oldSize; j++ )
  800.           pushBack( at( j ) );
  801.  
  802.         Copying.copy( first, q, myStart.copy( left ) );
  803.         }
  804.       else
  805.         {
  806.         int index = oldSize - n;
  807.  
  808.         for ( int j = index; j < oldSize; j++ )
  809.           pushBack( at( j ) );
  810.  
  811.         DequeIterator i = myStart.copy( left );
  812.         Copying.copyBackward( i, myStart.copy( index ), myStart.copy( oldSize) );
  813.         Copying.copy( first, last, myStart.copy( left ) );
  814.         }
  815.       }
  816.     }
  817.  
  818.   /**
  819.    * Remove all elements that match a particular object and return the numbers of
  820.    * objects that were removed.
  821.    * @param object The object to remove.
  822.    * @return The number of objects removed.
  823.    */
  824.   public int remove( Object object )
  825.     {
  826.     return remove( 0, myLength - 1, object );
  827.     }
  828.  
  829.   /**
  830.    * Remove at most a given number of elements that match a particular object and return the number of
  831.    * objects that were removed.
  832.    * @param object The object to remove.
  833.    * @param count The maximum number of objects to remove.
  834.    * @return The number of objects removed.
  835.    */
  836.   public synchronized int remove( Object object, int count )
  837.     {
  838.     int removed = 0;
  839.     while ( count > 0 )
  840.       {
  841.       int i = indexOf( object );
  842.       if ( i >= 0 )
  843.         {
  844.         --count;
  845.         ++removed;
  846.         remove( i );
  847.         }
  848.       }
  849.     return removed;
  850.     }
  851.  
  852.   /**
  853.    * Remove all elements within a range of indices that match a particular object
  854.    * and return the number of objects that were removed.
  855.    * @param first The index of the first object to consider.
  856.    * @param last The index of the last object to consider.
  857.    * @param object The object to remove.
  858.    * @return The number of objects removed.
  859.    * @exception java.lang.IndexOutOfBoundsException If either index is invalid.
  860.    */
  861.   public synchronized int remove( int first, int last, Object object )
  862.     {
  863.     if ( last < first )
  864.       return 0;
  865.  
  866.     checkRange( first, last );
  867.     DequeIterator firstx = myStart.copy( first );
  868.     DequeIterator lastx = myStart.copy( last + 1 );
  869.     DequeIterator finish = (DequeIterator) Removing.remove( firstx, lastx, object );
  870.     int n = finish.distance( lastx );
  871.     remove( finish, lastx );
  872.     return n;
  873.     }
  874.  
  875.   /**
  876.    * Replace all elements that match a particular object with a new value and return
  877.    * the number of objects that were replaced.
  878.    * @param oldValue The object to be replaced.
  879.    * @param newValue The value to substitute.
  880.    */
  881.   public synchronized int replace( Object oldValue, Object newValue )
  882.     {
  883.     return Replacing.replace( this, oldValue, newValue );
  884.     }
  885.  
  886.   /**
  887.    * Replace all elements within a range of indices that match a particular object
  888.    * with a new value and return the number of objects that were replaced.
  889.    * @param first The index of the first object to be considered.
  890.    * @param last The index of the last object to be considered.
  891.    * @param oldValue The object to be replaced.
  892.    * @param newValue The value to substitute.
  893.    * @exception java.lang.IndexOutOfBoundsException If either index is invalid.
  894.    */
  895.   public synchronized int replace( int first, int last, Object oldValue, Object newValue )
  896.     {
  897.     if ( last < first )
  898.       return 0;
  899.  
  900.     checkRange( first, last );
  901.     return Replacing.replace( myStart.copy( first ), myStart.copy( last + 1 ), oldValue, newValue );
  902.     }
  903.  
  904.   /**
  905.    * Return the number of objects that match a particular value.
  906.    * @param object The object to count.
  907.    */
  908.   public synchronized int count( Object object )
  909.     {
  910.     return Counting.count( this, object );
  911.     }
  912.  
  913.   /**
  914.    * Return the number of objects within a particular range of indices that match a
  915.    * particular value.
  916.    * @param first The index of the first object to consider.
  917.    * @param last The index of the last object to consider.
  918.    * @exception java.lang.IndexOutOfBoundsException If either index is invalid.
  919.    */
  920.   public synchronized int count( int first, int last, Object object )
  921.     {
  922.     if ( last < first )
  923.       return 0;
  924.  
  925.     checkRange( first, last );
  926.     return Counting.count( myStart.copy( first ), myStart.copy( last + 1 ), object );
  927.     }
  928.  
  929.   /**
  930.    * Return the index of the first object that matches a particular value, or -1
  931.    * if the object is not found.
  932.    * @param object The object to find.
  933.    */
  934.   public synchronized int indexOf( Object object )
  935.     {
  936.     DequeIterator i = (DequeIterator) Finding.find( myStart, myFinish, object );
  937.     return i.atEnd() ? -1 : myStart.distance( i );
  938.     }
  939.  
  940.   /**
  941.    * Return the index of the first object within a range of indices that match a
  942.    * particular object, or -1 if the object is not found.
  943.    * @param first The index of the first object to consider.
  944.    * @param last The index of the last object to consider.
  945.    * @param object The object to find.
  946.    * @exception java.lang.IndexOutOfBoundsException If either index is invalid.
  947.    */
  948.   public synchronized int indexOf( int first, int last, Object object )
  949.     {
  950.     if ( last < first )
  951.       return -1;
  952.  
  953.     checkRange( first, last );
  954.     DequeIterator end = myStart.copy( last + 1 );
  955.     DequeIterator i = (DequeIterator) Finding.find( myStart.copy( first ), end, object );
  956.     return i.equals( end ) ? -1 : myStart.distance( i );
  957.     }
  958.  
  959.   /**
  960.    * Return true if I contain a particular object.
  961.    * @param object The object in question.
  962.    */
  963.   public boolean contains( Object object )
  964.     {
  965.     return indexOf( object ) != -1;
  966.     }
  967.  
  968.   private void growMap()
  969.     {
  970.     // Create space for new map that is twice the size of the current map.
  971.     int newMapSize = myMap.length * 2;
  972.     Object[][] tmp = new Object[ newMapSize ][];
  973.  
  974.     // Copy the old map to the new map.
  975.     int i = newMapSize / 4;
  976.     int count = myFinish.myMapIndex - myStart.myMapIndex + 1;
  977.     System.arraycopy( myMap, myStart.myMapIndex, tmp, i, count );
  978.  
  979.     // Update the start, finish, and map variables.
  980.     myFinish.myMapIndex = i;
  981.     myStart.myMapIndex = i + count - 1;
  982.     myMap = tmp;
  983.     }
  984.  
  985.   private void createMap()
  986.     {
  987.     myMap = new Object[ Allocator.pageSize() ][];
  988.     int mapIndex = myMap.length / 2;
  989.     myMap[ mapIndex ] = new Object[ BLOCK_SIZE ];
  990.     int blockIndex = BLOCK_SIZE / 2;
  991.     myStart.myBlockIndex = blockIndex;
  992.     myStart.myMapIndex = mapIndex;
  993.     myFinish.myBlockIndex = blockIndex;
  994.     myFinish.myMapIndex = mapIndex;
  995.     }
  996.  
  997.   private void checkRange( int lo, int hi )
  998.     {
  999.     if ( lo < 0 || lo >= myLength )
  1000.       throw new IndexOutOfBoundsException( "Attempt to access index " + lo + " when valid range is 0.." + (myLength - 1) );
  1001.  
  1002.     if ( hi < 0 || hi >= myLength )
  1003.       throw new IndexOutOfBoundsException( "Attempt to access index " + hi + " when valid range is 0.." + (myLength - 1) );
  1004.     }
  1005.   }
  1006.