home *** CD-ROM | disk | FTP | other *** search
/ ActiveX Programming Unleashed CD / AXU.iso / jgl_1_1 / jgl_1_1.exe / src / SList.java < prev    next >
Encoding:
Java Source  |  1996-09-10  |  29.9 KB  |  1,061 lines

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