import java.util.Iterator;

public class LinkedList<Element> {
  private int size;
  private Node first;
  public class Node {
    private Element element;
    private Node next;
    private Node(Element element) {
      this.element = element;
      next = null;
    }
  }
  public Node getFirst() { return first;}
  private class LinkedListIterator implements Iterator<Element> {
    private Node current;
    private LinkedListIterator() {
      current = first;
    }
    public boolean hasNext() {
      return current != null;
    }
    public Element next() {
      Element e = current.element;
      current = current.next;
      return e;
    }
    public void remove() {
      throw new UnsupportedOperationException();
    }
  }
  public LinkedList() {
    first = null;
    size = 0;
  }
  public int size() { return size; }
  public int capacity() {return size; }
  private Node getNode(int index) {
    Node p = first;
    for (int pos = 0; pos < index; pos++)
      p = p.next;
    return p;
  }
  public Element get(int index) {
    return getNode(index).element;
  }
  public Element set(int index, Element element) {
    Node p = getNode(index);
    Element old = p.element;
    p.element = element;
    return old;
  }
  public int indexOf(Element element) {
    Node p = first;
    for (int i = 0; i < size; i++)
      if (element.equals(p.element))
        return i;
      else
        p = p.next;
    return -1;
  }
  public void add(Element element) {
    add(size, element);
  }
  public void add(int index, Element element) {
    Node newNode = new Node(element);
    if (index == 0) {
      newNode.next = first;
      first = newNode;
    }
    else {
      Node prev = getNode(index-1);
      newNode.next = prev.next;
      prev.next = newNode;
    }
    size++;
  }
  public void remove(int index) {
    if (index == 0)
      first = first.next;
    else {
      Node prev = getNode(index-1);
      prev.next = prev.next.next;
    }
    size--;
  }
  public Iterator<Element> iterator() {
    return new LinkedListIterator();
  }
  public String toString() {
    StringBuffer buf = new StringBuffer("[");
    for (Node p = first; p != null; p = p.next) {
      buf.append(p.element.toString());
      if (p.next != null)
        buf.append(",");
    }
    buf.append("]");
    return buf.toString();
  }
}