/** * Remove and return the first element in the list. * * @return an <code>Object</code> value */ @SuppressWarnings({"unchecked"}) public T removeFirst() { T o = _head; if ( o == null ) { return null; } T n = o.getNext(); o.setNext( null ); if ( null != n ) { n.setPrevious( null ); } _head = n; if ( --_size == 0 ) { _tail = null; } return o; }
/** Empties the list. */ public void clear() { if ( null != _head ) { for ( TLinkable<T> link = _head.getNext(); link != null; link = link.getNext() ) { TLinkable<T> prev = link.getPrevious(); prev.setNext( null ); link.setPrevious( null ); } _head = _tail = null; } _size = 0; }
/** * Remove and return the last element in the list. * * @return an <code>Object</code> value */ @SuppressWarnings({"unchecked"}) public T removeLast() { T o = _tail; if ( o == null ) { return null; } T prev = o.getPrevious(); o.setPrevious( null ); if ( null != prev ) { prev.setNext( null ); } _tail = prev; if ( --_size == 0 ) { _head = null; } return o; }
/** * Return the node following the given node. This method exists for two reasons: * <ol> * <li>It's really not recommended that the methods implemented by TLinkable be * called directly since they're used internally by this class.</li> * <li>This solves problems arising from generics when working with the linked * objects directly.</li> * </ol> * <p/> * NOTE: this should only be used with nodes contained in the list. The results are * undefined with anything else. * * @param current The current node * @return the node after the current node */ @SuppressWarnings({"unchecked"}) public T getNext( T current ) { return current.getNext(); }
/** {@inheritDoc} */ @Override @SuppressWarnings({"unchecked"}) public T get( int index ) { // Blow out for bogus values if ( index < 0 || index >= _size ) { throw new IndexOutOfBoundsException( "Index: " + index + ", Size: " + _size ); } // Determine if it's better to get there from the front or the back if ( index > ( _size >> 1 ) ) { int position = _size - 1; T node = _tail; while ( position > index ) { node = node.getPrevious(); position--; } return node; } else { int position = 0; T node = _head; while ( position < index ) { node = node.getNext(); position++; } return node; } }
/** * Return the node preceding the given node. This method exists for two reasons: * <ol> * <li>It's really not recommended that the methods implemented by TLinkable be * called directly since they're used internally by this class.</li> * <li>This solves problems arising from generics when working with the linked * objects directly.</li> * </ol> * <p/> * NOTE: this should only be used with nodes contained in the list. The results are * undefined with anything else. * * @param current The current node * @return the node after the current node */ @SuppressWarnings({"unchecked"}) public T getPrevious( T current ) { return current.getPrevious(); }
/** * Implementation of index-based list insertions. * * @param index an <code>int</code> value * @param linkable an object of type TLinkable */ @SuppressWarnings({"unchecked"}) protected void insert( int index, T linkable ) { if ( _size == 0 ) { _head = _tail = linkable; // first insertion } else if ( index == 0 ) { linkable.setNext( _head ); // insert at front _head.setPrevious( linkable ); _head = linkable; } else if ( index == _size ) { // insert at back _tail.setNext( linkable ); linkable.setPrevious( _tail ); _tail = linkable; } else { T node = get( index ); T before = node.getPrevious(); if ( before != null ) { before.setNext( linkable ); } linkable.setPrevious( before ); linkable.setNext( node ); node.setPrevious( linkable ); } _size++; }
/** * Copies the list's contents into a native array. This will be a * shallow copy: the Tlinkable instances in the Object[] array * have links to one another: changing those will put this list * into an unpredictable state. Holding a reference to one * element in the list will prevent the others from being garbage * collected unless you clear the next/previous links. <b>Caveat * programmer!</b> * * @return an <code>Object[]</code> value */ public Object[] toArray() { Object[] o = new Object[_size]; int i = 0; for ( TLinkable link = _head; link != null; link = link.getNext() ) { o[i++] = link; } return o; }
/** {@inheritDoc} */ @Override @SuppressWarnings({"unchecked"}) public T get( int index ) { // Blow out for bogus values if ( index < 0 || index >= _size ) { throw new IndexOutOfBoundsException( "Index: " + index + ", Size: " + _size ); } // Determine if it's better to get there from the front or the back if ( index > ( _size >> 1 ) ) { int position = _size - 1; T node = _tail; while ( position > index ) { node = node.getPrevious(); position--; } return node; } else { int position = 0; T node = _head; while ( position < index ) { node = node.getNext(); position++; } return node; } }
/** * Return the node preceding the given node. This method exists for two reasons: * <ol> * <li>It's really not recommended that the methods implemented by TLinkable be * called directly since they're used internally by this class.</li> * <li>This solves problems arising from generics when working with the linked * objects directly.</li> * </ol> * <p/> * NOTE: this should only be used with nodes contained in the list. The results are * undefined with anything else. * * @param current The current node * @return the node after the current node */ @SuppressWarnings({"unchecked"}) public T getPrevious( T current ) { return current.getPrevious(); }
/** * Copies the list to a native array, destroying the next/previous * links as the copy is made. This list will be emptied after the * copy (as if clear() had been invoked). The Object[] array * returned will contain TLinkables that do <b>not</b> hold * references to one another and so are less likely to be the * cause of memory leaks. * * @return an <code>Object[]</code> value */ public Object[] toUnlinkedArray() { Object[] o = new Object[_size]; int i = 0; for ( TLinkable<T> link = _head, tmp; link != null; i++ ) { o[i] = link; tmp = link; link = link.getNext(); tmp.setNext( null ); // clear the links tmp.setPrevious( null ); } _size = 0; // clear the list _head = _tail = null; return o; }
TLinkable<T> link = (TLinkable<T>) o; p = link.getPrevious(); n = link.getNext(); } else if ( n == null ) { // this is the tail link.setPrevious( null ); p.setNext( null ); _tail = p; } else if ( p == null ) { // this is the head link.setNext( null ); n.setPrevious( null ); _head = n; } else { // somewhere in the middle p.setNext( n ); n.setPrevious( p ); link.setNext( null ); link.setPrevious( null );
/** * Inserts newElement into the list immediately before current. * All elements to the right of and including current are shifted * over. * * @param current a <code>TLinkable</code> value currently in the list. * @param newElement a <code>TLinkable</code> value to be added to * the list. */ public void addBefore( T current, T newElement ) { if ( current == _head ) { addFirst( newElement ); } else if ( current == null ) { addLast( newElement ); } else { T p = current.getPrevious(); newElement.setNext( current ); p.setNext( newElement ); newElement.setPrevious( p ); current.setPrevious( newElement ); _size++; } }
/** * A linear search for <tt>o</tt> in the list. * * @param o an <code>Object</code> value * @return a <code>boolean</code> value */ public boolean contains( Object o ) { for ( TLinkable<T> link = _head; link != null; link = link.getNext() ) { if ( o.equals( link ) ) { return true; } } return false; }
/** {@inheritDoc} */ @Override public T get( int index ) { // Blow out for bogus values if ( index < 0 || index >= _size ) { throw new IndexOutOfBoundsException( "Index: " + index + ", Size: " + _size ); } // Determine if it's better to get there from the front or the back if ( index > ( _size >> 1 ) ) { int position = _size - 1; T node = _tail; while ( position > index ) { node = node.getPrevious(); position--; } return node; } else { int position = 0; T node = _head; while ( position < index ) { node = node.getNext(); position++; } return node; } }
/** * Return the node preceding the given node. This method exists for two reasons: * <ol> * <li>It's really not recommended that the methods implemented by TLinkable be * called directly since they're used internally by this class.</li> * <li>This solves problems arising from generics when working with the linked * objects directly.</li> * </ol> * <p/> * NOTE: this should only be used with nodes contained in the list. The results are * undefined with anything else. * * @param current The current node * @return the node after the current node */ public T getPrevious( T current ) { return current.getPrevious(); }
/** * Inserts newElement into the list immediately after current. * All elements to the left of and including current are shifted * over. * * @param current a <code>TLinkable</code> value currently in the list. * @param newElement a <code>TLinkable</code> value to be added to * the list. */ public void addAfter( T current, T newElement ) { if ( current == _tail ) { addLast( newElement ); } else if ( current == null ) { addFirst( newElement ); } else { T n = current.getNext(); newElement.setPrevious( current ); newElement.setNext( n ); current.setNext( newElement ); n.setPrevious( newElement ); _size++; } }
/** Empties the list. */ public void clear() { if ( null != _head ) { for ( TLinkable<T> link = _head.getNext(); link != null; link = link.getNext() ) { TLinkable<T> prev = link.getPrevious(); prev.setNext( null ); link.setPrevious( null ); } _head = _tail = null; } _size = 0; }
/** * Remove and return the last element in the list. * * @return an <code>Object</code> value */ @SuppressWarnings({"unchecked"}) public T removeLast() { T o = _tail; if ( o == null ) { return null; } T prev = o.getPrevious(); o.setPrevious( null ); if ( null != prev ) { prev.setNext( null ); } _tail = prev; if ( --_size == 0 ) { _head = null; } return o; }
/** * Executes <tt>procedure</tt> for each entry in the list. * * @param procedure a <code>TObjectProcedure</code> value * @return false if the loop over the values terminated because * the procedure returned false for some value. */ @SuppressWarnings({"unchecked"}) public boolean forEachValue( TObjectProcedure<T> procedure ) { T node = _head; while ( node != null ) { boolean keep_going = procedure.execute( node ); if ( !keep_going ) { return false; } node = node.getNext(); } return true; }