public void add(int index, E element) {
    if (index < 0 || index > size) {
      throw new IndexOutOfBoundsException("Index out of bounds: " + index);
    } else if (element == null) {
      throw new NullPointerException("Null elements not supported by list.");
    } else if (index == 0) {
      final LLNode<E> node = new LLNode<>(element);
      node.setNext(head);
      head.setPrev(node);
      head = node;
      size++;
    } else if (index == size) {
      final LLNode<E> node = new LLNode<>(element);
      tail.setNext(node);
      node.setPrev(tail);
      tail = node;
      size++;
    } else {
      final LLNode<E> node = new LLNode<>(element);
      LLNode<E> nextNode = new LLNode<>(null);
      nextNode = head;
      while (index > 0) {
        nextNode = nextNode.next;
        index--;
      }
      nextNode.prev.next = node;
      node.prev = nextNode.prev;
      node.next = nextNode;
      nextNode.prev = node;
      size++;
    }

    //    This method adds an element at the specified index.
    // If elements exist at that index, you will move elements at that
    // index (and beyond) up, effectively inserting this element at that location in the list.
    // Although drawings are helpful for implementing any method, you will benefit heavily from
    // drawing out what should happen in this method before trying to code it.
    // You will want to throw an IndexOutOfBoundsException if the index provided is not reasonable
    // for
    // inserting an element.
    // Optional: After authoring this version of the add method, you could consider removing
    // redundant
    // code by having the add method you originally wrote just call this method.
    // To test this method, use the method in MyLinkedListTester called testAddAtIndex.
  }
  /** Create a new empty doublyLinkedList */
  public MyLinkedList() {
    this.size = 0;
    this.head = new LLNode<E>(null);
    this.tail = new LLNode<E>(null);

    // Set the initial references
    head.setNext(tail);
    tail.setPrev(head);
  }