Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

I need help with the following Java code My methods that I need help with are: a

ID: 3908067 • Letter: I

Question

I need help with the following Java code

My methods that I need help with are: add(int pos, E obj), addAll(int pos, E obj), remove(int pos), reverse(), contains(), indexOf(E obj), lastIndexOf(E obj), removeAll(Collection c), retainAll(Collection c), toArray(), toArray(T[] arr), and the methods in the AdaptiveListIterator.

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;

public class AdaptiveList implements List {
   public class ListNode // private member of outer class
   {
       public E data; // public members:
       public ListNode link; // used outside the inner class
       public ListNode prev; // used outside the inner class

       public ListNode(E item) {
           data = item;
           link = prev = null;
       }
   }

   public ListNode head; // dummy node made public for testing.
   public ListNode tail; // dummy node made public for testing.
   private int numItems; // number of data items
   private boolean linkedUTD; // true if the linked list is up-to-date.

   public E[] theArray; // the array for storing elements
   private boolean arrayUTD; // true if the array is up-to-date.

   public AdaptiveList() {
       clear();
   }

   @Override
   public void clear() {
       head = new ListNode(null);
       tail = new ListNode(null);
       head.link = tail;
       tail.prev = head;
       numItems = 0;
       linkedUTD = true;
       arrayUTD = false;
       theArray = null;
   }

   /**
   * Returns true if linked list matches array
   *
   * @return
   */
   public boolean getlinkedUTD() {
       return linkedUTD;
   }

   /**
   * Returns true if theArray and the linked list match.
   *
   * @return
   */
   public boolean getarrayUTD() {
       return arrayUTD;
   }

   /**
   * AdaptiveList constructor that passes in Collection c as an argument
   * Instantiates an AdaptiveList with the contents of c loaded.
   *
   * @param c
   */
   public AdaptiveList(Collection c) {
       clear();
       addAll(c);
   }

   // Removes the node from the linked list.
   // This method should be used to remove a node from the linked list.
   /**
   * Removes toRemove from linked list.
   *
   * @param toRemove
   */
   private void unlink(ListNode toRemove) {
       if (toRemove == head || toRemove == tail)
           throw new RuntimeException("An attempt to remove head or tail");
       toRemove.prev.link = toRemove.link;
       toRemove.link.prev = toRemove.prev;
   }

   // Inserts new node toAdd right after old node current.
   // This method should be used to add a node to the linked list.
   /**
   * Inserts ListNode toAdd after ListNode current
   *
   * @param current
   * @param toAdd
   */
   private void link(ListNode current, ListNode toAdd) {
       if (current == tail)
           throw new RuntimeException("An attempt to link after tail");
       if (toAdd == head || toAdd == tail)
           throw new RuntimeException("An attempt to add head/tail as a new node");
       toAdd.link = current.link;
       toAdd.link.prev = toAdd;
       toAdd.prev = current;
       current.link = toAdd;
   }

   /**
   * Syncs theArray with the up-to-date linked list.
   *
   */
   private void updateArray() // makes theArray up-to-date.
   {
       if (numItems < 0)
           throw new RuntimeException("numItems is negative: " + numItems);
       if (!linkedUTD)
           throw new RuntimeException("linkedUTD is false");

       theArray = (E[]) (new Object[numItems]);
       AdaptiveListIterator ali = new AdaptiveListIterator();

       for (int i = 0; i < numItems; i++) {
           theArray[i] = ali.next();
       }
       arrayUTD = true;
   }

   /**
   * Syncs the linked list with the up-to-date array
   *
   */
   private void updateLinked() // makes the linked list up-to-date.
   {
       if (numItems < 0)
           throw new RuntimeException("numItems is negative: " + numItems);
       if (!arrayUTD)
           throw new RuntimeException("arrayUTD is false");

       if (theArray == null || theArray.length < numItems)
           throw new RuntimeException("theArray is null or shorter");

       for (int i = 0; i < numItems; i++) {
           head.link = tail;
           tail.prev = head;
           for (E element : theArray)
               add(element);
           linkedUTD = true;
       }
   }

   @Override
   public int size() {
       return numItems;
   }

   @Override
   public boolean isEmpty() {
       return head.link == tail;
   }

   @Override
   public boolean add(E obj) {
add(numItems, obj);
       return true; // may need to be revised.
   }

   @Override
   public boolean addAll(Collection c) {
addAll(numItems,c);

       return true; // may need to be revised.
   } // addAll 1

   @Override
   public boolean remove(Object obj) {
remove(indexOf(obj));
       return true;
   }

   /**
   * Not important
   *
   * @param pos
   */
   private void checkIndex(int pos) // a helper method
   {
       if (pos >= numItems || pos < 0)
           throw new IndexOutOfBoundsException("Index: " + pos + ", Size: " + numItems);
   }

   private void checkIndex2(int pos) // a helper method
   {
       if (pos > numItems || pos < 0)
           throw new IndexOutOfBoundsException("Index: " + pos + ", Size: " + numItems);
   }

   private void checkNode(ListNode cur) // a helper method
   {
       if (cur == null || cur == tail)
           throw new RuntimeException("numItems: " + numItems + " is too large");
   }

   private ListNode findNode(int pos) // a helper method
   {
       ListNode cur = head;
       for (int i = 0; i < pos; i++) {
           checkNode(cur);
           cur = cur.link;
       }
       checkNode(cur);
       return cur;
   }

   @Override
   public void add(int pos, E obj) {
       if (pos < 0 || pos > size())
           throw new IndexOutOfBoundsException();
      
//TODO

   }

   @Override
   public boolean addAll(int pos, Collection c) {
       if (c == null || c.isEmpty())
           return false;

       if (pos < 0 || pos > size())
           throw new IndexOutOfBoundsException();


           //TODO

  

       return true; // may need to be revised.
   } // addAll 2

   @Override
   public E remove(int pos) {
       if (pos < 0 || pos > size())
           throw new IndexOutOfBoundsException();




   }

   @Override
   public E get(int pos) {
//       updateLinked();
       if (pos < 0 || pos > size())
           throw new IndexOutOfBoundsException();

       AdaptiveListIterator adli = new AdaptiveListIterator();
       for (int i = 0; i < pos; i++) {
           adli.next();
       }
       return adli.next(); // may need to be revised.
   }

   @Override
   public E set(int pos, E obj) {
       updateArray();
       if (pos < 0 || pos > size())
           throw new IndexOutOfBoundsException();
      
       theArray[pos] = obj;
      
//       AdaptiveListIterator adli = new AdaptiveListIterator();
//       for (int i = 0; i <= pos; i++) {
//           System.out.println(adli.next());
//       }
//       adli.set(obj);
//       updateArray();
//       System.out.println(this);
       return obj; // may need to be revised.
   }

   public boolean reverse() {
       if (size() <= 1)
           return false;
      
//TODO
       return true; // may need to be revised.
   }

   @Override

//Note a list can contain null items
   public boolean contains(Object obj) {
       AdaptiveListIterator c = new AdaptiveListIterator();
       for (int i = 0; i < numItems; i++) {
           if (c.next() == obj)
               return true;
       }
       return false;
   }

   @Override
   public boolean containsAll(Collection c) {
       Iterator temp = c.iterator();

       while (temp.hasNext()) {
           if (!contains(temp.next())) {
               return false;
           }
       }
       return true; // may need to be revised.
   } // containsAll

   @Override
   public int indexOf(Object obj) {
       if (this.isEmpty())
           return -1;
      
       AdaptiveListIterator adli = new AdaptiveListIterator();
       int index = 0;
      
       while (adli.hasNext()) {
           if (!adli.next().equals(obj)) {
               index++;
           } else {
               return index;
           }
       }
       return -1;
   }

   @Override
   public int lastIndexOf(Object obj) {
       if (this.isEmpty())
           return -1;
      
       AdaptiveListIterator adli = new AdaptiveListIterator();
       int running = 0;
       int lastIndex = -1;
      
       while (adli.hasNext()) {
           if (!adli.next().equals(obj)) {
               running++;
           } else {
               lastIndex = running++;
           }
       }
       return lastIndex; // may need to be revised.
   }

   @Override
   public boolean removeAll(Collection c) {

       return true; // may need to be revised.
   }

   @Override
   public boolean retainAll(Collection c) {
  

       return true; // may need to be revised.
   }

   @Override
   public Object[] toArray() {

   }

   @Override
   public T[] toArray(T[] arr) {

       return tmp; // may need to be revised.
   }

   @Override
   public List subList(int fromPos, int toPos) {
       throw new UnsupportedOperationException();
   }

   private class AdaptiveListIterator implements ListIterator {
       private int index; // index of next node;
       private ListNode cur; // node at index - 1
       private ListNode last; // node last visited by next() or previous()
      
       /**
       * Default constructor
       * Updates linked list if not already up to date.
       * Puts cur between head and tail.
       *
       */
       public AdaptiveListIterator() {
           if (!linkedUTD)
               updateLinked();
//TODO
           index = 0;
       }

       /**
       * Constructor passes in int pos
       * updates linked list
       * puts puts cur at pos inside the list
       *
       * @param pos
       */
       public AdaptiveListIterator(int pos) {
           if (!linkedUTD)
               updateLinked();
//TODO
       }

       @Override
       public boolean hasNext() {
           return cur.link != tail;
       }

       @Override
       public E next() {
           if (hasNext()) {
//TODO
           } else {
               throw new NoSuchElementException();
           }
       }

       @Override
       public boolean hasPrevious() {
           return cur.prev != head;
       }

       @Override
       public E previous() {
           if (hasPrevious()) {
               cur.link = cur.prev;
//TODO

           } else {
               throw new NoSuchElementException();
           }
       }

       @Override
       public int nextIndex() {
           return index;
       }

       @Override
       public int previousIndex() {
           return index - 1;
       }
      
       /**
       * removes the element which cur most recently passed over
       *
       */
       public void remove() {
           if (last != null) {
//TODO

           } else {
               throw new IllegalStateException();
           }
       }
      
       /**
       * Inserts obj at cur's position in the list and puts cur ahead of obj
       *
       * @param obj
       */
       public void add(E obj) {
//TODO

       } // add

       @Override
       public void set(E obj) {
           if (last != null) {
              //TODO
           } else {
               throw new IllegalStateException();
           }
       } // set
   } // AdaptiveListIterator

   @Override
   public boolean equals(Object obj) {
       if (!linkedUTD)
           updateLinked();
       if ((obj == null) || !(obj instanceof List))
           return false;
       List list = (List) obj;
       if (list.size() != numItems)
           return false;
       Iterator iter = list.iterator();
       for (ListNode tmp = head.link; tmp != tail; tmp = tmp.link) {
           if (!iter.hasNext())
               return false;
           Object t = iter.next();
           if (!(t == tmp.data || t != null && t.equals(tmp.data)))
               return false;
       }
       if (iter.hasNext())
           return false;
       return true;
   } // equals

   @Override
   public Iterator iterator() {
       return new AdaptiveListIterator();
   }

   @Override
   public ListIterator listIterator() {
       return new AdaptiveListIterator();
   }

   @Override
   public ListIterator listIterator(int pos) {
       checkIndex2(pos);
       return new AdaptiveListIterator(pos);
   }

   // Adopted from the List interface.
   @Override
   public int hashCode() {
       if (!linkedUTD)
           updateLinked();
       int hashCode = 1;
       for (E e : this)
           hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
       return hashCode;
   }

   // You should use the toString*() methods to see if your code works as expected.
   @Override
   public String toString() {
       String eol = System.getProperty("line.separator");
       return toStringArray() + eol + toStringLinked();
   }
  
   /**
   * Returns a string interpretation of theArray
   *
   * @return
   */
   public String toStringArray() {
       String eol = System.getProperty("line.separator");
       StringBuilder strb = new StringBuilder();
       strb.append("A sequence of items from the most recent array:" + eol);
       strb.append('[');
       if (theArray != null)
           for (int j = 0; j < theArray.length;) {
               if (theArray[j] != null)
                   strb.append(theArray[j].toString());
               else
                   strb.append("-");
               j++;
               if (j < theArray.length)
                   strb.append(", ");
           }
       strb.append(']');
       return strb.toString();
   }

   /**
   * calls toStringLinked(null)
   *
   * @return
   */
   public String toStringLinked() {
       return toStringLinked(null);
   }

   // iter can be null.
   /**
   * uses iter to move over the linked list and return a string
   * interpretation of the list.
   *
   * @param iter
   * @return
   */
   public String toStringLinked(ListIterator iter) {
       int cnt = 0;
       int loc = iter == null ? -1 : iter.nextIndex();

       String eol = System.getProperty("line.separator");
       StringBuilder strb = new StringBuilder();
       strb.append("A sequence of items from the most recent linked list:" + eol);
       strb.append('(');
       for (ListNode cur = head.link; cur != tail;) {
           if (cur.data != null) {
               if (loc == cnt) {
                   strb.append("| ");
                   loc = -1;
               }
               strb.append(cur.data.toString());
               cnt++;

               if (loc == numItems && cnt == numItems) {
                   strb.append(" |");
                   loc = -1;
               }
           } else
               strb.append("-");

           cur = cur.link;
           if (cur != tail)
               strb.append(", ");
       }
       strb.append(')');
       return strb.toString();
   }
}

Note the following:

NullPointerException cannot be thrown from our add methods, since we allow null to be added, check below example.

AdaptiveList adtl = new AdaptiveList<>();

adtl.add(null);

adtl.add("A");

System.out.println(adtl);

System.out.println(adtl.get(0));

would output:

A sequence of items from most recent array:

[ ]

A sequence of items from most recent linked array:

(-, A)

null

Example

AdaptiveList adt = new AdaptiveList<>();

adt.addAll(Arrays.asList("A","B","C"));

System.out.println(Arrays.toString(adt.toArray()));   // [A, B, C]

adt.set(1, null);

System.out.println(Arrays.toString(adt.toArray())); // [A, null, C]

ListIterator lr = adt.listIterator();

System.out.println(lr.previousIndex()+"|"+lr.nextIndex());   // -1|0

System.out.println(lr.next()); // A

System.out.println(lr.previousIndex()+"|"+lr.nextIndex());   // 0|1

lr.set(null);

System.out.println(lr.previousIndex()+"|"+lr.nextIndex());   // 0|1

System.out.println(lr.next()); // null

System.out.println(lr.previousIndex()+"|"+lr.nextIndex());   // 1|2

Also note that the indexOf and lastIndexOf method should be able to find the index of a null value as long as the list has at least one item. For example with list.add(1), list.add(null), list.add(4). The indexOf(null) should return 1.

Explanation / Answer

Since your question containing many subpart. I am not going to answer every subpart. What i am going to answer is add, addAll and remove method fuctionality. I am pasting the code for that and if you are not able to understand my answer kindly let me know. I also want to suggest that if you paste your code then atleast it should not contain compile time error. Kindly take care of that.

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;

public class AdaptiveList<E> implements List<E> {

public class ListNode<E> // private member of outer class
{
public E data; // public members:
public ListNode link; // used outside the inner class
public ListNode prev; // used outside the inner class

public ListNode(E item) {
data = item;
link = prev = null;
}
}

public ListNode head; // dummy node made public for testing.
public ListNode tail; // dummy node made public for testing.
private int numItems; // number of data items
private boolean linkedUTD; // true if the linked list is up-to-date.

public E[] theArray; // the array for storing elements
private boolean arrayUTD; // true if the array is up-to-date.

public AdaptiveList() {
clear();
}

@Override
public void clear() {
head = new ListNode(null);
tail = new ListNode(null);
head.link = tail;
tail.prev = head;
numItems = 0;
linkedUTD = true;
arrayUTD = false;
theArray = null;
}

/**
* Returns true if linked list matches array
*
* @return
*/
public boolean getlinkedUTD() {
return linkedUTD;
}

/**
* Returns true if theArray and the linked list match.
*
* @return
*/
public boolean getarrayUTD() {
return arrayUTD;
}

/**
* AdaptiveList constructor that passes in Collection c as an argument
* Instantiates an AdaptiveList with the contents of c loaded.
*
* @param c
*/
public AdaptiveList(Collection c) {
clear();
addAll(c);
}

// Removes the node from the linked list.
// This method should be used to remove a node from the linked list.
/**
* Removes toRemove from linked list.
*
* @param toRemove
*/
private void unlink(ListNode toRemove) {
if (toRemove == head || toRemove == tail)
throw new RuntimeException("An attempt to remove head or tail");
toRemove.prev.link = toRemove.link;
toRemove.link.prev = toRemove.prev;
}

// Inserts new node toAdd right after old node current.
// This method should be used to add a node to the linked list.
/**
* Inserts ListNode toAdd after ListNode current
*
* @param current
* @param toAdd
*/
private void link(ListNode current, ListNode toAdd) {
if (current == tail)
throw new RuntimeException("An attempt to link after tail");
if (toAdd == head || toAdd == tail)
throw new RuntimeException("An attempt to add head/tail as a new node");
toAdd.link = current.link;
toAdd.link.prev = toAdd;
toAdd.prev = current;
current.link = toAdd;
}

/**
* Syncs theArray with the up-to-date linked list.
*
*/
private void updateArray() // makes theArray up-to-date.
{
if (numItems < 0)
throw new RuntimeException("numItems is negative: " + numItems);
if (!linkedUTD)
throw new RuntimeException("linkedUTD is false");

theArray = (E[]) (new Object[numItems]);
AdaptiveListIterator ali = new AdaptiveListIterator();

for (int i = 0; i < numItems; i++) {
theArray[i] = (E) ali.next();
}
arrayUTD = true;
}

/**
* Syncs the linked list with the up-to-date array
*
*/
private void updateLinked() // makes the linked list up-to-date.
{
if (numItems < 0)
throw new RuntimeException("numItems is negative: " + numItems);
if (!arrayUTD)
throw new RuntimeException("arrayUTD is false");

if (theArray == null || theArray.length < numItems)
throw new RuntimeException("theArray is null or shorter");

for (int i = 0; i < numItems; i++) {
head.link = tail;
tail.prev = head;
for (E element : theArray)
add(element);
linkedUTD = true;
}
}

@Override
public int size() {
return numItems;
}

@Override
public boolean isEmpty() {
return head.link == tail;
}

@Override
public boolean add(E obj) {
add(numItems, obj);
return true; // may need to be revised.
}

@Override
public boolean addAll(Collection c) {
addAll(numItems,c);

return true; // may need to be revised.
} // addAll 1

@Override
public boolean remove(Object obj) {
remove(indexOf(obj));
return true;
}

/**
* Not important
*
* @param pos
*/
private void checkIndex(int pos) // a helper method
{
if (pos >= numItems || pos < 0)
throw new IndexOutOfBoundsException("Index: " + pos + ", Size: " + numItems);
}

private void checkIndex2(int pos) // a helper method
{
if (pos > numItems || pos < 0)
throw new IndexOutOfBoundsException("Index: " + pos + ", Size: " + numItems);
}

private void checkNode(ListNode cur) // a helper method
{
if (cur == null || cur == tail)
throw new RuntimeException("numItems: " + numItems + " is too large");
}

private ListNode findNode(int pos) // a helper method
{
ListNode cur = head;
for (int i = 0; i < pos; i++) {
checkNode(cur);
cur = cur.link;
}
checkNode(cur);
return cur;
}

@Override
public void add(int pos, E obj) {
if (pos < 0 || pos > size())
throw new IndexOutOfBoundsException();
if (pos == size())
linkLast(obj);
else
linkBefore(obj, findNode(pos));
//TODO

}

/**
* Inserts element e before non-null Node succ.
*/
void linkBefore(E e, ListNode<E> succ) {
final ListNode<E> pred = succ.prev;
final ListNode<E> newNode = new ListNode<>(e);
newNode.prev=pred;
newNode.link=succ;
succ.prev = newNode;
if (pred == null)
head = newNode;
else
pred.link = newNode;
numItems++;
}
/**
* Links e as last element.
*/
void linkLast(E e) {
final ListNode<E> l = tail;
final ListNode<E> newNode = new ListNode<E>(e);
tail = newNode;
if (l == null)
head = newNode;
else
l.link = newNode;
numItems++;
}

@Override
public boolean addAll(int pos, Collection c) {
if (c == null || c.isEmpty())
return false;

if (pos < 0 || pos > size())
throw new IndexOutOfBoundsException();
Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false;

ListNode<E> pred, succ;
if (pos == numItems) {
succ = null;
pred = tail;
} else {
succ = findNode(pos);
pred = succ.prev;
}

for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
ListNode<E> newNode = new ListNode<>(e);
newNode.prev=pred;
if (pred == null)
head = newNode;
else
pred.link = newNode;
pred = newNode;
}

if (succ == null) {
tail = pred;
} else {
pred.link = succ;
succ.prev = pred;
}

numItems += numNew;
return true;
} // addAll 2

@Override
public E remove(int pos) {
if (pos < 0 || pos > size())
throw new IndexOutOfBoundsException();
AdaptiveListIterator adli = new AdaptiveListIterator();
for (int i = 0; i < pos; i++) {
adli.next();
}
E value=(E)adli.next();
ListNode element=findNode(pos);
unlink(element);
return value;

}

@Override
public E get(int pos) {
// updateLinked();
if (pos < 0 || pos > size())
throw new IndexOutOfBoundsException();

AdaptiveListIterator adli = new AdaptiveListIterator();
for (int i = 0; i < pos; i++) {
adli.next();
}
return (E) adli.next(); // may need to be revised.
}

@Override
public E set(int pos, E obj) {
updateArray();
if (pos < 0 || pos > size())
throw new IndexOutOfBoundsException();
  
theArray[pos] = obj;
  
// AdaptiveListIterator adli = new AdaptiveListIterator();
// for (int i = 0; i <= pos; i++) {
// System.out.println(adli.next());
// }
// adli.set(obj);
// updateArray();
// System.out.println(this);
return obj; // may need to be revised.
}

public boolean reverse() {
if (size() <= 1)
return false;
  
//TODO
return true; // may need to be revised.
}

@Override

//Note a list can contain null items
public boolean contains(Object obj) {
AdaptiveListIterator c = new AdaptiveListIterator();
for (int i = 0; i < numItems; i++) {
if (c.next() == obj)
return true;
}
return false;
}

@Override
public boolean containsAll(Collection c) {
Iterator temp = c.iterator();

while (temp.hasNext()) {
if (!contains(temp.next())) {
return false;
}
}
return true; // may need to be revised.
} // containsAll

@Override
public int indexOf(Object obj) {
if (this.isEmpty())
return -1;
  
AdaptiveListIterator adli = new AdaptiveListIterator();
int index = 0;
  
while (adli.hasNext()) {
if (!adli.next().equals(obj)) {
index++;
} else {
return index;
}
}
return -1;
}

@Override
public int lastIndexOf(Object obj) {
if (this.isEmpty())
return -1;
  
AdaptiveListIterator adli = new AdaptiveListIterator();
int running = 0;
int lastIndex = -1;
  
while (adli.hasNext()) {
if (!adli.next().equals(obj)) {
running++;
} else {
lastIndex = running++;
}
}
return lastIndex; // may need to be revised.
}

@Override
public boolean removeAll(Collection c) {

return true; // may need to be revised.
}

@Override
public boolean retainAll(Collection c) {
  

return true; // may need to be revised.
}

@Override
public Object[] toArray() {
return null;

}

@Override
public <T> T[] toArray(T[] arr) {
T[] tmp = null;

return tmp; // may need to be revised.
}

@Override
public List subList(int fromPos, int toPos) {
throw new UnsupportedOperationException();
}

private class AdaptiveListIterator<E> implements ListIterator<E> {
private int index; // index of next node;
private ListNode cur; // node at index - 1
private ListNode last; // node last visited by next() or previous()
  
/**
* Default constructor
* Updates linked list if not already up to date.
* Puts cur between head and tail.
*
*/
public AdaptiveListIterator() {
if (!linkedUTD)
updateLinked();
//TODO
index = 0;
}

/**
* Constructor passes in int pos
* updates linked list
* puts puts cur at pos inside the list
*
* @param pos
*/
public AdaptiveListIterator(int pos) {
if (!linkedUTD)
updateLinked();
//TODO
}

@Override
public boolean hasNext() {
return cur.link != tail;
}

@Override
public E next() {
if (hasNext()) {
//TODO
} else {
throw new NoSuchElementException();
}
return null;
}

@Override
public boolean hasPrevious() {
return cur.prev != head;
}

@Override
public E previous() {
if (hasPrevious()) {
cur.link = cur.prev;
//TODO

} else {
throw new NoSuchElementException();
}
return null;
}

@Override
public int nextIndex() {
return index;
}

@Override
public int previousIndex() {
return index - 1;
}
  
/**
* removes the element which cur most recently passed over
*
*/
public void remove() {
if (last != null) {
//TODO

} else {
throw new IllegalStateException();
}
}
  
/**
* Inserts obj at cur's position in the list and puts cur ahead of obj
*
* @param obj
*/
public void add(E obj) {
//TODO

} // add

@Override
public void set(E obj) {
if (last != null) {
//TODO
} else {
throw new IllegalStateException();
}
} // set
} // AdaptiveListIterator

@Override
public boolean equals(Object obj) {
if (!linkedUTD)
updateLinked();
if ((obj == null) || !(obj instanceof List))
return false;
List list = (List) obj;
if (list.size() != numItems)
return false;
Iterator iter = list.iterator();
for (ListNode tmp = head.link; tmp != tail; tmp = tmp.link) {
if (!iter.hasNext())
return false;
Object t = iter.next();
if (!(t == tmp.data || t != null && t.equals(tmp.data)))
return false;
}
if (iter.hasNext())
return false;
return true;
} // equals

@Override
public Iterator iterator() {
return new AdaptiveListIterator();
}

@Override
public ListIterator listIterator() {
return new AdaptiveListIterator();
}

@Override
public ListIterator listIterator(int pos) {
checkIndex2(pos);
return new AdaptiveListIterator(pos);
}

// Adopted from the List interface.
@Override
public int hashCode() {
if (!linkedUTD)
updateLinked();
int hashCode = 1;
for (E e : this)
hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
return hashCode;
}

// You should use the toString*() methods to see if your code works as expected.
@Override
public String toString() {
String eol = System.getProperty("line.separator");
return toStringArray() + eol + toStringLinked();
}
  
/**
* Returns a string interpretation of theArray
*
* @return
*/
public String toStringArray() {
String eol = System.getProperty("line.separator");
StringBuilder strb = new StringBuilder();
strb.append("A sequence of items from the most recent array:" + eol);
strb.append('[');
if (theArray != null)
for (int j = 0; j < theArray.length;) {
if (theArray[j] != null)
strb.append(theArray[j].toString());
else
strb.append("-");
j++;
if (j < theArray.length)
strb.append(", ");
}
strb.append(']');
return strb.toString();
}

/**
* calls toStringLinked(null)
*
* @return
*/
public String toStringLinked() {
return toStringLinked(null);
}

// iter can be null.
/**
* uses iter to move over the linked list and return a string
* interpretation of the list.
*
* @param iter
* @return
*/
public String toStringLinked(ListIterator iter) {
int cnt = 0;
int loc = iter == null ? -1 : iter.nextIndex();

String eol = System.getProperty("line.separator");
StringBuilder strb = new StringBuilder();
strb.append("A sequence of items from the most recent linked list:" + eol);
strb.append('(');
for (ListNode cur = head.link; cur != tail;) {
if (cur.data != null) {
if (loc == cnt) {
strb.append("| ");
loc = -1;
}
strb.append(cur.data.toString());
cnt++;

if (loc == numItems && cnt == numItems) {
strb.append(" |");
loc = -1;
}
} else
strb.append("-");

cur = cur.link;
if (cur != tail)
strb.append(", ");
}
strb.append(')');
return strb.toString();
}
}